Note:
You may assume k is always valid, 1 ≤ k ≤ n^2.
2. Implementation
(1) Binary Search
思路: 为什么二分法的结果是正确的呢? 首先在二分法,我们知道要第k小的数一定在矩阵里,也即start <= res <= end, 而二分结束的条件是start >= end, 所以start == right == res。
class Solution {
public int kthSmallest(int[][] matrix, int k) {
if (matrix == null || matrix.length == 0 || k < 0) {
return -1;
}
int m = matrix.length, n = matrix[0].length;
int start = matrix[0][0], end = matrix[m - 1][n - 1], mid = 0;
int count = 0;
while (start < end) {
mid = start + (end - start) / 2;
count = searchAndCount(mid, matrix);
if (count < k) {
start = mid + 1;
}
else {
end = mid;
}
}
return start;
}
public int searchAndCount(int num, int[][] matrix) {
int row = matrix.length - 1, col = 0, count = 0;
while (row >= 0 && col < matrix[0].length) {
if (matrix[row][col] <= num) {
count += (row + 1);
++col;
}
else {
--row;
}
}
return count;
}
}
(2) Heap
class Solution {
public int kthSmallest(int[][] matrix, int k) {
int n = matrix.length;
PriorityQueue<CellInfo> minHeap = new PriorityQueue<>();
for (int j = 0; j < n; j++) {
minHeap.add(new CellInfo(0, j, matrix[0][j]));
}
for (int i = 1; i < Math.min(k, n * n); i++) {
CellInfo curCell = minHeap.remove();
int curRow = curCell.row;
int curCol = curCell.col;
if (curRow + 1 < n) {
minHeap.add(new CellInfo(curRow + 1, curCol, matrix[curRow + 1][curCol]));
}
}
return minHeap.peek().val;
}
class CellInfo implements Comparable<CellInfo> {
int row;
int col;
int val;
public CellInfo(int row, int col, int val) {
this.row = row;
this.col = col;
this.val = val;
}
public int compareTo(CellInfo that) {
return this.val - that.val;
}
}
}