All pairs with max heap
Generate all possible pairs keeping smallest in a max heap.
Time: , space:
from heapq import heappush as push, heappop as pop
class Solution:
def smallestDistancePair(self, nums: List[int], k: int) -> int:
maxq = []
n = len(nums)
for i in range(n-1):
for j in range(i+1, n):
dist = abs( nums[i] - nums[j] )
push( maxq, -dist )
if len(maxq) > k:
pop(maxq)
return -maxq[0]
Sorting and minq
We want to generate the pairs in sorted order of distance. Sort nums, put pairs having different first elements in a minq. These are like heads of sorted linked lists. Now pop
times and return the top distance.
Time: , space:
.
from heapq import heappush as push, heappop as pop
class Solution:
def smallestDistancePair(self, nums: List[int], k: int) -> int:
n = len(nums)
nums.sort()
minq = []
for i in range(n-1):
dist = abs( nums[i]-nums[i+1] )
push( minq, ( dist, (i, i+1) ) )
while k > 1:
k -= 1
d, coords = pop( minq )
i, j = coords
if j == n-1:
continue
j += 1
d = abs( nums[i]-nums[j] )
push( minq, (d, (i, j)) )
kth, _ = minq[0]
return kth
Reformulate and binary search
If we have a monotonic function like , we can find the minimum
such that
using binary-search. We use
mid as the and depending on whether
, we can move left or right.
Let be a function that counts the pairs in
nums having distance at most . This is a monotonic function because, if we increase
,
either increases or remains the same, but never decreases. In other words, as we increase
, if we keep asking, “Is
“, we have the sequence of answers like:
. So, the boolean version
behaves like a step function.
The time complexity of the binary-search is .
For this problem, if we have sorted nums, we can find the count of pairs with a given maximum distance of in
time.
Time complexity: where
is the distance between smallest and largest elements in
nums. Space: that of sorting.
class Solution:
def has_kth_smallest(self, nums, k, max_distance) -> bool:
n = len(nums)
start, pair_count = 0, 0
for end in range(n):
# If no pairs with this end,
# start == end, we get pair_count += 0
while abs( nums[end]-nums[start] ) > max_distance:
start += 1
pair_count += (end-start)
return pair_count >= k
def smallestDistancePair(self, nums: List[int], k: int) -> int:
n = len(nums)
# For efficient has_kth_smallest()
nums.sort()
lo, hi = 0, nums[-1]-nums[0]
kth = -1
while lo <= hi:
mid = (lo+hi) // 2
if self.has_kth_smallest(nums, k, mid):
kth = mid
hi = mid-1
else:
lo = mid+1
return kth
Leave a comment