題目描述:給定整數陣列 nums,定義任意兩個元素之差的絕對值為「距離」。在所有 C(n, 2) 對的距離中,找出第 k 小的距離。
解題思路:直接生成所有對距離排序的做法需要 O(n^2) 空間,不可取。改用「二分搜尋答案」策略:先排序陣列,答案範圍為 [0, nums[n-1] - nums[0]]。對每個候選距離 mid,用滑動視窗計算有多少對距離 ≤ mid。具體地,固定右端點 r,用指針 l 找到最左端滿足 nums[r] - nums[l] <= mid 的位置,以右端點為 r 的合法對數為 r - l。若總對數 ≥ k,代表第 k 小的距離 ≤ mid,縮小上界;否則增大下界。由於陣列已排序,滑動視窗的左指針只會向右移,整體為線性時間。
時間複雜度:O(n log n + n log W) — 排序需 O(n log n);二分搜尋共 O(log W) 輪(W = nums[n-1] - nums[0]),每輪的滑動視窗計數為 O(n),合計 O(n log W)。
空間複雜度:O(1)(不計排序用的輔助空間) — 排序為原地操作,計數函數只使用常數個指針與計數器。
1. Sort nums
2. lo = 0, hi = nums[n-1] - nums[0]
3. While lo < hi:
a. mid = lo + (hi - lo) / 2
b. count = countPairs(nums, mid) using sliding window:
- l = 0
- for r from 1 to n-1:
while nums[r] - nums[l] > mid: l++
count += r - l
c. If count >= k: hi = mid
d. Else: lo = mid + 1
4. Return lo
note: binary search finds the smallest distance d such that
countPairs(d) >= k方法一:暴力排序 — O(n^2 log n)
枚舉所有 C(n, 2) 對,計算距離後排序,直接取第 k 個。時間 O(n^2 log n),空間 O(n^2)。在 n=10^4 時產生 5*10^7 個元素,會超時與超記憶體,僅適合小規模驗證。
方法二:桶排序輔助計數 — O(n^2 + W) 先用 O(n^2) 統計每個距離值出現的次數填入桶中,再從 0 開始累加直到累積次數 ≥ k。時間 O(n^2 + W),空間 O(W)(W 為最大距離),在距離範圍小時有競爭力,但不如二分搜尋 + 滑動視窗通用。
lo 對應的距離值在陣列中並不存在,會造成問題嗎?countPairs 函數中,當陣列有重複元素時,距離為 0 的對也會被正確計入嗎?請用具體例子驗證。