↓快轉到主要內容
  1. LeetCode/

LeetCode 719: Find K-th Smallest Pair Distance

·2 分鐘· ·
LeetCode Hard Binary-Search Two-Pointers Sliding-Window Sorting
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-09-06

  • 提交紀錄:Accepted → Accepted(整理變數名稱)

解題思路
#

Pair 數量是 n(n-1)/2,n = 10^4 時大約 5 * 10^7,全部列出來再排序太慢。

改成對答案二分:

  • 距離的範圍是 [0, max - min]。
  • count(d) = 距離 <= d 的 pair 數,d 越大 count 越大,是單調的。
  • 第一個讓 count(d) >= k 的 d,就是第 k 小的距離。

count(d) 怎麼算:先排序,用滑動窗口。對每個右端 right,把左端往右推到 nums[right] - nums[left] <= d,這時 left 到 right - 1 都能和 right 配成距離 <= d 的 pair,共 right - left 對。

我的解法
#

class Solution:
    def smallestDistancePair(self, nums: List[int], k: int) -> int:
        nums.sort()
        n = len(nums)

        def count_within(d: int) -> int:
            count = left = 0
            for right in range(n):
                while nums[right] - nums[left] > d:
                    left += 1
                count += right - left
            return count

        lo, hi = 0, nums[-1] - nums[0]
        while lo < hi:
            mid = (lo + hi) // 2
            if count_within(mid) < k:
                lo = mid + 1
            else:
                hi = mid
        return lo

為什麼答案一定是真實存在的距離
#

二分找到的是「第一個讓 count >= k 的 d」。如果 d 不是任何 pair 的距離,那 count(d) == count(d - 1),d - 1 也滿足條件,就跟「第一個」矛盾。所以答案一定是某個 pair 的距離。

複雜度
#

時間 O(n log n + n log W),W 是最大距離。空間 O(1),不算排序。

要特別避免的錯誤
#

  • 列出所有 pair 再排序:O(n^2 log n)。
  • 用 heap 一個一個彈出第 k 小:k 可能到 5 * 10^7。
  • count 的時候每個 right 都從頭掃 left:要讓 left 只往前走。

面試口說整理
#

Pair 太多不能全部列出,所以我對距離二分:距離不超過 d 的 pair 數對 d 是單調的,第一個讓數量達到 k 的 d 就是答案。數 pair 時先排序,用滑動窗口:對每個右端把左端推到差距不超過 d,中間都能配對,加上 right - left。每次數 O(n),總共 O(n log n + n log W)。

相關文章

LeetCode 2968: Apply Operations to Maximize Frequency Score
·1 分鐘
LeetCode Hard Sliding-Window Sorting Prefix-Sum Binary-Search Array
LeetCode 2968 解題筆記:排序後,把一段全部變成同一個值,最省的目標是中位數;用前綴和 O(1) 算花費,花費隨視窗變大而變大,可以滑動
LeetCode 3323: Minimize Connected Groups by Inserting Interval
·1 分鐘
LeetCode Medium Sliding-Window Sorting Binary-Search Array
LeetCode 3323 解題筆記:先合併區間;新區間能把第 l 到 r 組連起來 ⇔ 第 r 組的起點 − 第 l 組的終點 <= k;滑動視窗找一次能連起來最多組
LeetCode 2972: Count the Number of Incremovable Subarrays II
·1 分鐘
LeetCode Hard Two-Pointers Binary-Search Array
LeetCode 2972 解題筆記:刪掉一段後留下嚴格遞增的前綴 + 後綴;對每個合法的前綴結尾,用只往右走的指針找第一個能接上的後綴起點,後面的起點都能選
LeetCode 2302: Count Subarrays With Score Less Than K
·1 分鐘
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2302 解題筆記:分數 = 總和 × 長度,都是正數,視窗越大分數越大;分數 >= k 就縮左邊,以 right 結尾的合法子陣列有 right - left + 1 個
LeetCode 1838: Frequency of the Most Frequent Element
·1 分鐘
LeetCode Medium Sliding-Window Sorting Greedy Prefix-Sum Binary-Search Array
LeetCode 1838 解題筆記:排序後,把視窗裡的數都加到 nums[right] 的花費是 nums[right] × 長度 − 視窗總和;花費 > k 就縮左邊
LeetCode 2271: Maximum White Tiles Covered by a Carpet
·1 分鐘
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 2271 解題筆記:地毯的左端放在某段白磚的起點一定不會更差;排序後用雙指針,完整蓋住的段累加,最後一段只算部分