373. 查找和最小的 K 对数字
2023-07-09 本文已影响0人
红树_
题目
给定两个以 非递减顺序排列 的整数数组 nums1
和 nums2
, 以及一个整数 k
。定义一对值 (u,v)
,其中第一个元素来自 nums1
,第二个元素来自 nums2
。
请找到和最小的 k
个数对 (u1,v1)
, (u2,v2)
... (uk,vk)
。
输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
解题思路
-
堆:尝试了双指针发现不能解,因为有序所以数组下标不超过k个,使用优先队列小根堆模拟:假设
i,0
出堆则下一个可能的较小数对为i,1...n
;所有可把所有的i,0
入堆出堆后枚举j
入堆,也可反过来把所有的0,j
先入堆枚举i
入堆。
堆
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2)->{
return nums1[o1[0]] + nums2[o1[1]] - nums1[o2[0]] - nums2[o2[1]];
});
List<List<Integer>> ans = new ArrayList<>();
int m = nums1.length,n = nums2.length,maxLen = Math.min(m, k) ;
for (int i = 0; i < maxLen; i++)pq.offer(new int[]{i,0});
while (k-- > 0 && !pq.isEmpty()) {
int[] idxPair = pq.poll();
List<Integer> list = new ArrayList<>();
list.add(nums1[idxPair[0]]);
list.add(nums2[idxPair[1]]);
ans.add(list);
if (idxPair[1] + 1 < n) {
pq.offer(new int[]{idxPair[0], idxPair[1] + 1});
}
}
return ans;
}
}
复杂度分析
- 时间复杂度:
O(klogmin(n,k))
,n
为数组长度,循环遍历k
次得到k
个数对,每次堆的操作时间复杂度为logmin(n,k)
。 - 空间复杂度:
O(min(n,k))
,堆中最多存放的元素。