---
# System prepended metadata

title: 719. Find K-th Smallest Pair Distance
tags: [leetcode]

---

# 719. Find K-th Smallest Pair Distance
#### Difficulty: Hard
link: https://leetcode.com/problems/find-k-th-smallest-pair-distance/

### 1. Binary Search
#### $O(n\ log\ (max(nums) - min(nums)) + n\ log\ n)$ runtime, $O(1)$ space

找第k個距離的問題，暴力的做法是找出所有pairs之間的距離，排序後找出第k個。然而，找所有pairs距離的時間複雜度是$O(n^2)$，排序的時間複雜度是$O(n^2\ log\ n^2)$，太慢了。

問題可以被轉變成，每次都猜一個距離，檢查這個距離是不是排在第k個之後，利用binary search找出滿足這個條件的最小值，便是答案。

套用binary search模板，距離的上下限是0到$max(nums) - min(nums)$。

關鍵在，怎麼設計feasible這個函數。

首先，利用絕對值的特性，將nums排序好，如此一來距離近的元素就會被放在一起。

為避免重複計算到pairs的距離，我們用一個for迴圈，作為pair的右邊(index是 $r$)，同時往左邊看，與num距離istance的數字(index是 $l$)，這之間pairs的距離都小於distance，用total來累加計算pairs數。

由於nums是排序好的，利用sliding window的作法，每次 $l$ 不用從開始檢查，從上次 $l$ 的位置開始往右就好，如此一來feasible函數的複雜度僅是$O(n)$。

時間複雜度為Binary search的$O(n\ log\ (max(nums) - min(nums))$和排序的$O(n\ log\ n)$的總和。

##### python
```python=
class Solution:
    def smallestDistancePair(self, nums: List[int], k: int) -> int:
        nums.sort()
        
        def feasible(distance):
            l, total = 0, 0
            for r, num in enumerate(nums):
                while nums[l] < num - distance:
                    l += 1
                total += r - l
                # early stop
                if total >= k:
                    return True
            return False
        
        left, right = 0, max(nums) - min(nums)
        
        while left < right:
            mid = left + (right - left) // 2
            if feasible(mid):
                right = mid
            else:
                left = mid + 1
        
        return left
```

###### tags: `leetcode`