LC.P1439[有序矩阵中的第k个最小数组和]

方法一:暴力(遍历+排序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int kthSmallest(int[][] mat, int k) {
int n = mat[0].length;
List<Integer> pre = new ArrayList<>(k), cur = new ArrayList<>(n * k);
pre.add(0);
for (int[] row : mat) {
cur.clear();
for (int a : pre) {
for (int b : row) {
cur.add(a + b);
}
}
Collections.sort(cur);
pre.clear();
for (int i = 0; i < Math.min(k, cur.size()); ++i) {
pre.add(cur.get(i));
}
}
return pre.get(k - 1);
}
}
  • 时间复杂度:$O(m \times n \times k \times log(n \times k))$
  • 空间复杂度:$O(n \times k)$

方法二:最小堆

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
class Solution {
public int kthSmallest(int[][] mat, int k) {
var a = new int[]{0};
for (var row : mat)
a = kSmallestPairs(row, a, k);
return a[k - 1];
}

// 373. 查找和最小的 K 对数字
private int[] kSmallestPairs(int[] nums1, int[] nums2, int k) {
int n = nums1.length, m = nums2.length, sz = 0;
var ans = new int[Math.min(k, n * m)];
var pq = new PriorityQueue<int[]>((a, b) -> a[0] - b[0]);
pq.add(new int[]{nums1[0] + nums2[0], 0, 0});
while (!pq.isEmpty() && sz < k) {
var p = pq.poll();
int i = p[1], j = p[2];
ans[sz++] = nums1[i] + nums2[j]; // 数对和
if (j == 0 && i + 1 < n)
pq.add(new int[]{nums1[i + 1] + nums2[0], i + 1, 0});
if (j + 1 < m)
pq.add(new int[]{nums1[i] + nums2[j + 1], i, j + 1});
}
return ans;
}
}
  • 时间复杂度:$O(m \times k \times log(min(n, k)))$
  • 空间复杂度:$O(min(n, k))$