Solution to LeetCode 373 Find K Pairs with Smallest Sums.
LeetCode 373
Find K Pairs with Smallest Sums (Medium). [link]
Priority queue using min heap. Add the k pairs of first k of
nums1with the first element ofnums2((0,0), (1,0), … (k,0)) intopq. Every time we pop out the first pair, push the pair with an increasednums2(e.g. pop (0,0), push (0,1)).Time complexity O(k log k). It takes O(k) to select k pairs of numbers. It takes O(logk) time complexity when popping into the heap queue and adjust the order. Space complexity O(k). The
pqonly stores k pairs of numbers.
class Solution(object):
def kSmallestPairs(self, nums1, nums2, k):
"""
:type nums1: List[int]
:type nums2: List[int]
:type k: int
:rtype: List[List[int]]
"""
result = []
pq = [(nums1[i] + nums2[0], i, 0) for i in range(min(len(nums1), k))]
while pq and len(result) < k:
_, i, j = heappop(pq)
result.append([nums1[i], nums2[j]])
if j + 1 < len(nums2):
heappush(pq, (nums1[i] + nums2[j+1], i, j+1))
return result
Binary search. We aim to find the minimal sum of pairs
xsuch that there are the number of pairs exceedk. We can do binary search with a sliding window, because of the property of this problem:- If the sum of pairs is less than
x, then the number of pairs is less thank. - If the sum of pairs is not less than
x, then the number of pairs is no less thank.
After we get
x, we add pairs with sum of them no more thanx. Then we add pairs with sum of them equal toxuntil the total number isk.Time complexity O(k + (len(nums1) + len(nums2))* log (range(nums1) + range(nums2))). Binary search takes log (range(nums1) + range(nums2)) time complexity, where range(nums1) = max(nums1) - min(nums1). Sliding window for searching takes O(2 * (k + m + n). Space complexity O(1).
- If the sum of pairs is less than
class Solution(object):
def kSmallestPairs(self, nums1, nums2, k):
"""
:type nums1: List[int]
:type nums2: List[int]
:type k: int
:rtype: List[List[int]]
"""
l, r = nums1[0] + nums2[0], nums1[-1] + nums2[-1] + 1
while l < r: # binary search [l, r)
m = l + (r - l) // 2
count = 0
i, j = 0, len(nums2) -1
while i < len(nums1) and j >= 0: # sliding window
if nums1[i] + nums2[j] > m: # find minimized SUM
j -= 1
else:
count += j+1
i += 1
if count < k: # find kth smallest pairs SUM
l = m + 1
else:
r = m
SUM = l
result = []
# find pairs with the sum smaller than SUM
i = len(nums2) -1
for n1 in nums1:
while i >= 0 and n1 + nums2[i] >= SUM:
i -= 1 # find the smallest nums2
for j in range(i + 1):
result.append([n1, nums2[j]])
if len(result) == k:
return result
# find pairs with the sum equal to SUM (if len(result) < k)
i = len(nums2) - 1
for n1 in nums1:
while i >= 0 and n1 + nums2[i] > SUM:
i -= 1
j = i
while j >= 0 and n1 + nums2[j] == SUM:
result.append([n1, nums2[j]])
if len(result) == k:
return result
j -= 1
return result