1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
private static class HeapNode {
int row;
int col;
int num;

HeapNode(int _row, int _col, int _num) {
row = _row;
col = _col;
num = _num;
}
}

public int kthSmallest(int[][] matrix, int k) {
int initialHeapSize = Math.min(matrix.length, k);
PriorityQueue<HeapNode> minHeap = new PriorityQueue<>((a, b) -> a.num - b.num);
for (int i = 0; i < initialHeapSize; i++) {
minHeap.offer(new HeapNode(i, 0, matrix[i][0]));
}
int count = 0;
while (count < k - 1) {
HeapNode currNode = minHeap.poll();
int currRow = currNode.row, currCol = currNode.col;
if (currCol + 1 < matrix[0].length) {
minHeap.offer(new HeapNode(currRow, currCol + 1, matrix[currRow][currCol + 1]));
}
count += 1;
}
return minHeap.peek().num;
}
}

N sorted lists求第K小. 这种类型题的解题思路要知道就是用Heap. 我们用heap存N个行每行的第0个元素, 然后开始poll. poll出来的我们查它所在的行和列, 把这一行下一个元素再请到heap里. 以此类推. 当我们poll了k - 1次时, 此时heap的顶就是答案. 由于我们是每行每列都sort了, 那么我们有时候没必要把每一行的第0个元素都装进heap里面, 比如如果有100行, k只是5, 那么前五行的第0个元素装进heap就行了. 从第6行到最后一行的所有元素都不可能是答案. 因为第六行到最后一行里面最小的就是第六行第0个元素. 而第六行第0个元素又比第五行第0个元素大. 因此前五行的第0个元素其一当答案都不会第六行第0个元素当答案.

时间复杂度: 装heap那就是log(1) + log2 + log3 +…log(min(n, k)) = min(n, k)log(min(n, k)) log(n!)收敛于nlogn. 就是min(n, k)是m, 那么装heap这一步就是O(mlogm). 然后每次poll再装是O(1) + O(logm), 一共K - 1次, 那就是O(Klogm), 加在一起就是O((K + m)logm).
空间复杂度: O(m) 也就是heap的大小.