0378. 有序矩阵中第 K 小的元素【中等】
1. 📝 题目描述
给你一个 n x n 矩阵 matrix,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。
你必须找到一个内存复杂度优于 O(n^2) 的解决方案。
示例 1:
txt
输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8
输出:13
解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 131
2
3
2
3
示例 2:
txt
输入:matrix = [[-5]], k = 1
输出:-51
2
2
提示:
n == matrix.lengthn == matrix[i].length1 <= n <= 300-10^9 <= matrix[i][j] <= 10^9- 题目数据 保证
matrix中的所有行和列都按 非递减顺序 排列 1 <= k <= n^2
进阶:
- 你能否用一个恒定的内存(即
O(1)内存复杂度)来解决这个问题? - 你能在
O(n)的时间复杂度下解决这个问题吗?这个方法对于面试来说可能太超前了,但是你会发现阅读这篇文章( this paper )很有趣。
2. 🎯 s.1 - 二分查找
c
int kthSmallest(int** matrix, int matrixSize, int* matrixColSize, int k) {
int n = matrixSize;
int lo = matrix[0][0], hi = matrix[n - 1][n - 1];
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int count = 0, j = n - 1;
for (int i = 0; i < n; i++) {
while (j >= 0 && matrix[i][j] > mid) j--;
count += j + 1;
}
if (count < k) lo = mid + 1;
else hi = mid;
}
return lo;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
js
/**
* @param {number[][]} matrix
* @param {number} k
* @return {number}
*/
var kthSmallest = function (matrix, k) {
const n = matrix.length
let lo = matrix[0][0],
hi = matrix[n - 1][n - 1]
while (lo < hi) {
const mid = Math.floor((lo + hi) / 2)
let count = 0,
j = n - 1
for (let i = 0; i < n; i++) {
while (j >= 0 && matrix[i][j] > mid) j--
count += j + 1
}
if (count < k) lo = mid + 1
else hi = mid
}
return lo
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
py
class Solution:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
n = len(matrix)
lo, hi = matrix[0][0], matrix[n - 1][n - 1]
while lo < hi:
mid = (lo + hi) // 2
count, j = 0, n - 1
for i in range(n):
while j >= 0 and matrix[i][j] > mid:
j -= 1
count += j + 1
if count < k:
lo = mid + 1
else:
hi = mid
return lo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 时间复杂度:
,其中 是矩阵边长 - 空间复杂度:
算法思路:
- 对值域二分,每次统计矩阵中
的元素个数 - 利用行列单调性,从左下角开始统计,复杂度为