Given an n x n
matrix
where each of the rows and columns is sorted in ascending order, return the kth
smallest element in the matrix.
Note that it is the kth
smallest element in the sorted order, not the kth
distinct element.
You must find a solution with a memory complexity better than O(n2)
.
Example 1:
Input: matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8 Output: 13 Explanation: The elements in the matrix are [1,5,9,10,11,12,13,13,15], and the 8th smallest number is 13
Example 2:
Input: matrix = [[-5]], k = 1 Output: -5
Constraints:
n == matrix.length == matrix[i].length
1 <= n <= 300
-109 <= matrix[i][j] <= 109
matrix
are guaranteed to be sorted in non-decreasing order.1 <= k <= n2
Follow up:
O(1)
memory complexity)?O(n)
time complexity? The solution may be too advanced for an interview but you may find reading this paper fun.This problem asks to find the kth smallest element in a sorted matrix. The matrix is n x n, and each row and column is sorted in ascending order. A naive approach would be to flatten the matrix and sort it, but this would have O(n²) space complexity, violating the problem's constraint. A more efficient solution uses binary search.
Approach:
The core idea is to perform a binary search on the possible range of values in the matrix. The search space is bounded by the minimum element (matrix[0][0]
) and the maximum element (matrix[n-1][n-1]
).
For each mid
value during the binary search, we need to efficiently count how many elements in the matrix are less than or equal to mid
. This is done using a clever two-pointer approach. We start from the bottom-left corner of the matrix. If the current element is less than or equal to mid
, it means all the elements in the row above are also less than or equal to mid
. So, we add the number of elements in that row (i + 1
) to our count and move to the right column (j++
). Otherwise, if the current element is greater than mid
, it means all elements to the right in this row are also greater than mid
, so we move up (i--
). This process efficiently counts elements less than or equal to mid
without explicitly iterating through the entire matrix.
After counting, we compare the count with k
. If count
is greater than or equal to k
, it means the kth smallest element is less than or equal to mid
, so we continue searching in the lower half (right = mid
). Otherwise, the kth smallest element is greater than mid
, and we search in the upper half (left = mid + 1
). The binary search continues until left
and right
converge, at which point left
(or right
) holds the kth smallest element.
Time Complexity Analysis:
Therefore, the overall time complexity is O(n log n).
Space Complexity Analysis:
The solution uses only a constant amount of extra space for variables, regardless of the input matrix size. Thus, the space complexity is O(1).
Code Explanation (Python):
The Python code implements the described algorithm. Let's break it down:
class Solution:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
def check(matrix, mid, k, n): # Helper function to count elements <= mid
count = 0
i, j = n - 1, 0
while i >= 0 and j < n:
if matrix[i][j] <= mid:
count += i + 1
j += 1
else:
i -= 1
return count >= k
n = len(matrix)
left, right = matrix[0][0], matrix[n - 1][n - 1] # Initialize search space
while left < right: # Binary search
mid = (left + right) >> 1
if check(matrix, mid, k, n):
right = mid
else:
left = mid + 1
return left # left is the kth smallest element
The check
function efficiently counts the number of elements less than or equal to mid
using the two-pointer technique as explained above. The main function performs the binary search using this helper function.
The Java, C++, and Go codes implement the same algorithm with minor syntax differences. They all achieve the same time and space complexity.