题目难度: 中等
今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复
剑指offer2
就能看到该系列当前连载的所有文章了, 记得关注哦~
给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k 。
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。
请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。
[0,0]
的数字对就是最小的, 次小的则一定只可能是下标[0,1]
或者[1,0]
, 这就引出了下面的思路:
[sm,i,j]
[0,0]
对应的三元组加入堆中[sm,i,j]
, 将对应数字对[nums[i],nums[j]]
加入最终结果中, 并将紧邻它的数字对[i+1,j]
和[i,j+1]
各自对应的三元组加入堆中[1,2]
和堆顶[2,1]
同样都有紧邻数字对[2,2]
class Solution:
def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
# 注意可能添加重复元素, 所以需要v集合
if not nums1 or not nums2:
# 没有符合要求的数字对
return []
res = []
# 最小堆初始时存储[0,0]对应的三元组
pq = [(nums1[0] + nums2[0], 0, 0)]
# 集合初始化存储下标对(0,0)
v = {(0, 0)}
while len(res) < k and pq:
# 弹出当前最小的数字对, 并将其追加到最终结果中
_, i, j = heapq.heappop(pq)
res.append([nums1[i], nums2[j]])
for ii, jj in ((i + 1, j), (i, j + 1)):
# 将尚未遍历的紧邻数字对加入堆和集合中
if ii < len(nums1) and jj < len(nums2) and (ii, jj) not in v:
v.add((ii, jj))
heapq.heappush(pq, (nums1[ii] + nums2[jj], ii, jj))
return res
大家可以在下面这些地方找到我~😊
我的公众号: 算法精选, 欢迎大家扫码关注~😊