给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
示例:
matrix = [ [ 1, 5, 9], [10, 11, 13], [12, 13, 15] ], k = 8, 返回 13。
说明:
你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n2 。
Review:
可以使用二分法查找,目前还不太清楚为什么会快,按理说 堆排序 nk < 2klog2n
可见测试用例局限性
可以使用堆(优先队列)来做,也可以使用二分法,不过我设计了一个 nk的算法类似于贪心搜索
Code:
class Solution {
public int kthSmallest(int[][] matrix, int k) {
//记录列进度
int[] record = new int[matrix.length];
int res = Integer.MAX_VALUE;
for (int i = 0; i < k; i++) {
int min = Integer.MAX_VALUE;
int rec = 0;
for (int j = 0; j < record.length; j++) {
if (record[j]==matrix[0].length){
continue;
}
int is = matrix[j][record[j]];
if (is < min) {
min = is;
rec = j;
}
if (record[j]==0){
break;
}
}
record[rec]++;
res = min;
}
return res;
}
}
public int kthSmallest(int[][] matrix, int k) {
int n = matrix.length;
int m = matrix[0].length;
int low = matrix[0][0], high = matrix[n - 1][m - 1];
while (low <= high) {
int mid = low + (high - low) / 2;
if (lessNum(matrix, mid) >= k) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
private int lessNum(int[][] matrix, int val) {
int n = matrix.length;
int m = matrix[0].length;
int p = 0;
int ans = 0;
for (int i = n - 1; i >= 0; -- i) {
while (p < m && matrix[i][p] <= val) {
p ++ ;
}
ans += p;
}
return ans;
}