📅  最后修改于: 2023-12-03 15:37:39.717000             🧑  作者: Mango
给定两个长度为 $m$ 和 $n$ 且元素已按升序排好序的整数数组 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] 它们的和分别为 3, 5, 7,最小的和为 3。
有多种解法可以解决该问题,包括暴力、优先队列和归并排序法等。其中,归并排序法是最优解,时间复杂度为 $O(nlogn)$。
对于两个有序数组 nums1 和 nums2,假设 nums1 中的第 i 个数和 nums2 中的第 j 个数组成了和最小的一对数。则,这个数对一定满足以下两个条件:
基于这两个条件,可以通过归并排序来解决问题。具体地,我们可以按以下方式进行归并:
idx
,其中 idx[i] 表示 nums1 第 i
个元素与 nums2 某个元素组成的数对中,nums1 中的元素下标为 idx[i],nums2 中的元素下标为 i。例子:
输入:
nums1 = [1,7,11], nums2 = [2,4,6], k = 3
解释:
首先,将指针数组初始化为 [0, 0, 0]。然后,生成三元组数组 [(1+2, 0+1, [1, 2]), (7+2, 0+1, [1, 3]), (11+2, 0+1, [1, 4]), (1+4, 1+1, [2, 2]), (7+4, 1+1, [2, 3]), (11+4, 0+2, [2, 4]), (1+6, 2+1, [3, 2]), (7+6, 1+2, [3, 3]), (11+6, 0+3, [3, 4])] 并按照和的大小排序,得到 [(1+2, 0+1, [1, 2]), (1+4, 1+1, [2, 2]), (7+2, 0+1, [1, 3]), (7+4, 1+1, [2, 3]), (1+6, 2+1, [3, 2]), (11+2, 0+1, [1, 4]), (7+6, 1+2, [3, 3]), (11+4, 0+2, [2, 4]), (11+6, 0+3, [3, 4])]。最后,生成输出数组 [(1, 2), (1, 4), (1, 6)]。
代码如下:
from typing import List
def kSmallestPairs(nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
if not nums1 or not nums2 or not k:
return []
n1, n2 = len(nums1), len(nums2)
if k > n1 * n2:
k = n1 * n2
idx = [0] * n1
res = []
for _ in range(k):
min_sum, idx_min = float('inf'), -1
for i in range(n1):
if idx[i] < n2 and (s := nums1[i] + nums2[idx[i]]) < min_sum:
min_sum = s
idx_min = i
if idx_min == -1:
break
res.append([nums1[idx_min], nums2[idx[idx_min]]])
idx[idx_min] += 1
return res
本题中,我们介绍了如何使用归并排序来找到和最小的 k 对数。此外,我们还讨论了暴力和优先队列等其他解法。在实际工程中,我们根据具体情况选择合适的解法,以达到最优化的效果。