
Problem Statement
You are given an n x n
matrix where each row and each column is sorted in ascending order. Your task is to find the kth smallest element in the matrix when all elements are considered in a single sorted list.
Duplicates are counted in order. That means if a number appears more than once, each instance counts separately toward the kth position.
Your solution must be efficient and must avoid O(n²) memory complexity, implying that brute-force flattening and sorting of the matrix is not acceptable.
Examples
Example 1
Input:
matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
Output:
13
Explanation:
All elements in sorted order: [1, 5, 9, 10, 11, 12, 13, 13, 15] The 8th smallest element is 13.
Example 2
Input:
matrix = [[-5]], k = 1
Output:
-5
Constraints
n == matrix.length == matrix[i].length
1 <= n <= 300
-10^9 <= matrix[i][j] <= 10^9
- All rows and columns are sorted in non-decreasing order
1 <= k <= n²
Approach and Intuition
1. Min-Heap Approach (Heap-based Merge)
- Insert the first element of each row into a min-heap.
- Each heap node stores the element along with its row and column position.
- Repeatedly pop the smallest element and insert the next element in the same row (if available).
- The kth popped element is the answer.
Time Complexity: O(k log n) Space Complexity: O(n)
2. Binary Search on Values (Optimal)
Since the matrix is sorted row-wise and column-wise, perform binary search on the value range:
low = matrix[0][0]
,high = matrix[n-1][n-1]
For each
mid
value, count how many elements in the matrix are≤ mid
using a pointer starting from the bottom-left corner of the matrix.If the count is less than
k
, movelow
up; otherwise, movehigh
down.When
low == high
, that value is the kth smallest element.
Time Complexity: O(n log(max−min)) Space Complexity: O(1)
Why These Work
The matrix's sorted structure lets you efficiently:
- Access the smallest unseen elements (in the heap method).
- Count how many values are ≤ a given threshold (in binary search).
Both strategies meet the problem’s memory constraint and are preferable to flattening and sorting the full matrix.
Solutions
- Java
- Python
class Solution {
public int findKthSmallest(int[][] matrix, int k) {
int size = matrix.length;
int low = matrix[0][0], high = matrix[size - 1][size - 1];
while (low < high) {
int mid = low + (high - low) / 2;
int[] minMaxPair = {matrix[0][0], matrix[size - 1][size - 1]};
int count = this.countLessOrEqual(matrix, mid, minMaxPair);
if (count == k) return minMaxPair[0];
if (count < k) low = minMaxPair[1]; // search right
else high = minMaxPair[0]; // search left
}
return low;
}
private int countLessOrEqual(int[][] matrix, int mid, int[] minMaxPair) {
int count = 0;
int size = matrix.length, row = size - 1, col = 0;
while (row >= 0 && col < size) {
if (matrix[row][col] > mid) {
// Updates the smallest number greater than the middle value
minMaxPair[1] = Math.min(minMaxPair[1], matrix[row][col]);
row--;
} else {
// Updates the largest number less than the middle value
minMaxPair[0] = Math.max(minMaxPair[0], matrix[row][col]);
count += row + 1;
col++;
}
}
return count;
}
}
The given Java class, Solution
, presents a way to solve the problem of finding the k-th smallest element in a sorted matrix. The method findKthSmallest
is pivotal in how this solution operates, using a binary search approach to efficiently narrow down the possible values until the k-th smallest element is identified.
Here's how the solution operates:
- The binary search is set up between the smallest element in the matrix, at
matrix[0][0]
, and the largest element, atmatrix[size-1][size-1]
. - During each iteration of the while loop, the mid-value of the current range (
low
tohigh
) is calculated. - A pair,
minMaxPair
, initializes as the smallest and largest possible values from the matrix and aids in adjusting the search bounds. - The
countLessOrEqual
function is called with the current middle valuemid
, and it returns the number of elements that are less than or equal tomid
. It also updatesminMaxPair
to reflect the smallest value greater thanmid
and the largest value less thanmid
that are encountered during its execution.- The function increments the count of qualifying elements by navigating through the matrix, adjusting its count based on the positioning relative to
mid
.
- The function increments the count of qualifying elements by navigating through the matrix, adjusting its count based on the positioning relative to
- If the count matches
k
,minMaxPair[0]
is returned as it represents the k-th smallest value. - Depending on whether the count is lesser or greater than
k
, the search range is updated to either the right or the left segment respectively. - The loop continues until
low
equalshigh
, which thenlow
is returned as the result.
Throughout the process, this implementation leverages the sorted property of the matrix for efficient searching and counting, making it capable of handling large matrices with a time complexity better than a direct sorting approach which is typically O(n log n)
. This focused binary search ensures the method achieves the desired result with optimized performance.
class Solution:
def countLEQ(self, matrix, threshold, lowerBound, upperBound):
elementsCount, dimension = 0, len(matrix)
idxRow, idxCol = dimension - 1, 0
while idxRow >= 0 and idxCol < dimension:
if matrix[idxRow][idxCol] > threshold:
upperBound = min(upperBound, matrix[idxRow][idxCol])
idxRow -= 1
else:
lowerBound = max(lowerBound, matrix[idxRow][idxCol])
elementsCount += idxRow + 1
idxCol += 1
return elementsCount, lowerBound, upperBound
def findKthSmallest(self, matrix: List[List[int]], k: int) -> int:
dimension = len(matrix)
lower, upper = matrix[0][0], matrix[dimension - 1][dimension - 1]
while lower < upper:
middle = lower + (upper - lower) / 2
minElement, maxElement = matrix[0][0], matrix[dimension - 1][dimension - 1]
count, minElement, maxElement = self.countLEQ(matrix, middle, minElement, maxElement)
if count == k:
return minElement
if count < k:
lower = maxElement # search in higher range
else:
upper = minElement # search in lower range
return lower
The problem "Kth Smallest Element in a Sorted Matrix" involves finding the kth smallest element in an n x n matrix sorted in non-decreasing order both row-wise and column-wise. This Python solution efficiently determines the answer using a binary search approach combined with a counting mechanism.
Initialize the binary search bounds,
lower
andupper
, as the first and last elements in the matrix, respectively.Within the binary search, calculate the middle value between the current
lower
andupper
.Count how many matrix elements are less than or equal to this middle value. This count is done via the
countLEQ
method which iterates through the matrix efficiently by comparing elements.- Begin from the bottom-left corner of the matrix. If the current element is greater than the middle value, reduce the row index to move upwards; otherwise, increase the column index; this maintains the sorted order properties of the matrix.
- Simultaneously, adjust the
lowerBound
andupperBound
for the next iteration based on the currently considered element in the matrix.
Check the count of elements:
- If the count exactly matches
k
, theminElement
(lower bound reached during counting) is our answer. - If the count is less than
k
, focus the next iteration on the upper half of our search range. - Conversely, if the count is greater than
k
, adjust to search in the lower half.
- If the count exactly matches
The search continues until
lower
converges withupper
, which will then hold the value of the kth smallest element.
Through the use of binary search and a specific counting method, this solution handles the task with improved complexity over naive methods, effectively leveraging the sorted properties of the matrix.
No comments yet.