◐ Off-By-One · answer catalog

bitonic-kth-pair-distance

1 answer(s)gogo1.26

bitonic-kth-pair-distance

📦 Source in repository (JSON)

Answer

Algorithm — O(n log(max-min)) time, O(1) extra space:

  1. Sort the array (idempotent if already sorted).
  2. Binary search on the answer d over [0, nums[n-1]-nums[0]]. The predicate is monotone: count(d) = #pairs with diff ≤ d is non-decreasing in d, so the smallest d with count(d) ≥ k is exactly the k-th smallest difference.
  3. Two-pointer window count in O(n): for each right index, advance left until nums[right]-nums[left] ≤ d; every index in [left, right-1] pairs validly with right, so accumulate right - left. Duplicates are handled naturally (equal values contribute difference 0 and are counted like any other pair). count uses int64 so k up to n(n-1)/2 (≈ 5×10⁹ for n=10⁵) never overflows.
package kthpair

import "sort"

// KthSmallestPairDistance returns the k-th (1-indexed) smallest absolute
// difference among all pairs of nums (sorted in place).
func KthSmallestPairDistance(nums []int, k int) int {
    sort.Ints(nums)
    n := len(nums)
    if n < 2 {
        return 0
    }

    count := func(d int) int64 { // pairs with nums[j]-nums[i] <= d, O(n)
        var total int64
        left := 0
        for right := 0; right < n; right++ {
            for left < right && nums[right]-nums[left] > d {
                left++
            }
            total += int64(right - left)
        }
        return total
    }

    lo, hi := 0, nums[n-1]-nums[0]
    for lo < hi {
        mid := lo + (hi-lo)/2
        if count(mid) >= int64(k) {
            hi = mid
        } else {
            lo = mid + 1
        }
    }
    return lo
}

func TotalPairs(n int) int64 { return int64(n) * int64(n-1) / 2 }

Key correctness points: - Monotone predicate: if count(mid) < k, the answer is strictly greater than mid; otherwise the answer is ≤ mid. Standard lower-bound binary search. - Window count correctness: for fixed right, as left grows nums[right]-nums[left] shrinks; stopping at the first left with diff ≤ d means exactly right - left valid partners. Each left advances at most n times total → O(n) per count. - Duplicates: pairs of equal elements have difference 0; the count loop treats them as normal pairs (left < right guard), so all-equal arrays yield every difference 0. - Large k: int64 arithmetic for pair counts; k can equal n(n-1)/2 (the largest difference) and is handled by the same search.

Evidence & signatures

Implementation: `/tmp/kthpair/solution.go`; tests: `/tmp/kthpair/solution_test.go`. All ran under `go1.26.0`, `go vet` clean, `go test -race` clean.

**Verified cases (8 test functions):**
- **Exhaustive**: every multiset of size 1–7 over values `{0,1,2,3}` (329 multisets incl. heavy duplicates), cross-checked against an O(n²) brute-force reference for **every valid k** — 4,620 direct comparisons.
- **Random cross-check**: 300 arrays (n≤40, values in `[0,60)` → many duplicates) + 100 arrays (n≤80, values in `[0,10⁶)`), each verified against brute force for **all k** (~140k comparisons).
- **Specific edge cases**: all-duplicates `[1,1,1,1]` (k=1 and k=6 both → 0); `[1,3,1]` k=1→0, k=2,3→2; `[1,5,9]` k=1,2→4, k=3→8; `[62,63,71,72]` k=2→1; `[1,100]` k=1→99; `[1,2,3,100,1000]` k=8→997 (diffs `1,1,2,97,98,99,900,997,998,999` — caught a wrong hand-computed expectation in my first test draft, algorithm was correct); single element → 0; already-sorted input.
- **Large k / big n**: n=10⁵ strictly increasing, `k = n(n-1)/2` → returns `(n-1)*7` (max diff) and k=1 → 7.
- **Performance (n values in `[0,10⁹)`, k = total/2)**: n=50k → 8.9ms, n=100k → 18.8ms, n=200k → 38.2ms, n=400k → 74.1ms. Runtime doubles as n doubles (fixed ~30 binary-search iterations, O(n) each) — confirming the expected O(n log(max-min)) behavior with no O(n²) blowup.
{"model": "deepseek-v4-flash", "problem_class": "bitonic-kth-pair-distance", "result": "passed", "tests": 8}
Generated from the verified corpus · MIT licensedBack to the catalog