二分查找:求解《719. 找出第 K 小的数对距离》

2022-06-15 13:38:15
二分查找,求解《719. 找出第 K 小的数对距离》

例题

719. 找出第 K 小的数对距离

数对 (a,b) 由整数 a 和 b 组成,其数对距离定义为 a 和 b 的绝对差值。
给你一个整数数组 nums 和一个整数 k ,数对由 nums[i] 和 nums[j] 组成且满足 0 <= i < j < nums.length 。返回 所有数对距离中 第 k 小的数对距离。
示例 1:
输入:nums = [1,3,1], k = 1
输出:0
解释:数对和对应的距离如下:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
距离第 1 小的数对是 (1,1) ,距离为 0

答案

二分查找

var smallestDistancePair = function(nums, k) {
  nums.sort((a, b) => a - b)
  const n = nums.length
  return lower_bound(nums[n - 1] - nums[0], d => {
    let cnt = 0
    for (let j = 0; j < n; j++) {
      cnt += j - lower_bound(n - 1, m => nums[m] >= nums[j] - d)
    }
    return cnt >= k
  })
};
const lower_bound = (r, func) => {
  let l = 0
  while (l <= r) {
    const m = l + r >>> 1
    if (func(m)) r = m - 1
    else l = m + 1
  }
  return l
}
function smallestDistancePair(nums: number[], k: number): number {
  nums.sort((a, b) => a - b)
  const n = nums.length
  return lower_bound(nums[n - 1] - nums[0], d => {
    let cnt = 0
    for (let j = 0; j < n; j++) {
      cnt += j - lower_bound(n - 1, m => nums[m] >= nums[j] - d)
    }
    return cnt >= k
  })
};
function lower_bound(r: number, func: (i: number) => boolean): number {
  let l = 0
  while (l <= r) {
    const m = l + r >>> 1
    if (func(m)) r = m - 1
    else l = m + 1
  }
  return l
}
func smallestDistancePair(nums []int, k int) int {
  sort.Ints(nums)
  n := len(nums)
  return sort.Search(nums[n - 1] - nums[0], func(d int) bool {
    cnt := 0
    for j := 0; j < n; j++ {
      cnt += j - sort.Search(n - 1, func(i int) bool {
        return nums[i] >= nums[j] - d
      })
    }
    return cnt >= k
  })
}
class Solution {
  function smallestDistancePair($nums, $k) {
    sort($nums);
    $n = count($nums);
    return $this->lower_bound($nums[$n - 1] - $nums[0], function($d) use($nums, $n, $k) {
      $cnt = 0;
      for ($j = 0; $j < $n; $j++) $cnt += $j - $this->lower_bound($n - 1, function($m) use($nums, $j, $d) {
        return $nums[$m] >= $nums[$j] - $d;
      });
      return $cnt >= $k;
    });
  }
  function lower_bound($r, $func) {
    $l = 0;
    while ($l <= $r) {
      $m = $l + $r >> 1;
      if ($func($m)) $r = $m - 1;
      else $l = $m + 1;
    }
    return $l;
  }
}
class Solution {
  public int smallestDistancePair(int[] nums, int k) {
    Arrays.sort(nums);
    int n = nums.length;
    return lower_bound(nums[n - 1] - nums[0], k, d -> {
      int cnt = 0;
      for (int j = 0; j < n; j++) {
        cnt += j - lower_bound(n - 1, nums[j] - d, m -> nums[m]);
      }
      return cnt;
    });
  }
  public int lower_bound(int r, int k, Function<Integer, Integer> func) {
    int l = 0;
    while (l <= r) {
      int m = l + r >>> 1;
      if (func.apply(m) >= k) r = m - 1;
      else l = m + 1;
    }
    return l;
  }
}
class Solution(object):
  def smallestDistancePair(self, nums, k): # python 2.7.12
    def count(d):
      cnt = 0
      for j in range(0, n):
        cnt += j - bisect.bisect_left(nums, nums[j] - d)
      return cnt
    nums.sort()
    n = len(nums)
    l, r = 0, nums[n - 1] - nums[0]
    while l <= r:
      m = l + r >> 1
      if count(m) >= k: r = m - 1
      else: l = m + 1
    return l
class Solution:
  def smallestDistancePair(self, nums: List[int], k: int) -> int: # python 3.10
    def count(d):
      cnt = 0
      for j in range(0, n):
        cnt += j - bisect.bisect_left(nums, nums[j] - d)
      return cnt
    nums.sort()
    n = len(nums)
    return bisect.bisect_left(range(0, nums[n - 1] - nums[0]), k, key = count)