📅  最后修改于: 2023-12-03 15:37:39.701000             🧑  作者: Mango
给定两个长度为 $m$ 和 $n$ 的数组 nums1 和 nums2,以及一个整数 k。
定义一对值 $(u,v)$,其中第一个元素来自 nums1,第二个元素来自 nums2。
找到和最小的 k 对数字 $(u_1,v_1), (u_2,v_2) ... (u_k,v_k)$。
这道题的思路非常简单,我们把所有可能的数对都求出来,然后排序,最后取前 k 小的就可以了。
具体来说,我们可以用一个小根堆存储当前所有可能的数对,从桶底开始逐个加入,每次加入一个数对后,将它与它旁边和它上面的数对比较,如果更小就交换位置,直到放到合适的位置。
完成上述操作后,我们就可以在小根堆的前 k 个数里找到和最小的 k 对数字了。
class Solution:
def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
pairs = []
for i in nums1:
for j in nums2:
pairs.append([i, j])
def get_sum(pair):
return pair[0] + pair[1]
heap = []
for pair in pairs:
heapq.heappush(heap, (get_sum(pair), pair))
res = []
for i in range(min(k, len(heap))):
res.append(heapq.heappop(heap)[1])
return res
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> res = new ArrayList<>();
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[0] + a[1] - b[0] - b[1]);
for (int i : nums1) {
for (int j : nums2) {
heap.offer(new int[]{i, j});
}
}
for (int i = 0; i < k && !heap.isEmpty(); i++) {
int[] pair = heap.poll();
res.add(Arrays.asList(pair[0], pair[1]));
}
return res;
}
}
假设 nums1 的长度为 m,nums2 的长度为 n,那么我们一共会找出 mn 对数字,所以时间复杂度为 O(mn log(mn)),其中 log(mn) 是由于我们要在小根堆中维护元素,这涉及到了对数级别的时间复杂度。如果 k 很小,不超过 mn,那么实际的时间复杂度就为 O(k log(k))。