LeetCode 每日一题——719. 找出第 K 小的数对距离

1.题目描述

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 。

示例 2:

输入:nums = [1,1,1], k = 2
输出:0

示例 3:

输入:nums = [1,6,1], k = 3
输出:5

2.解题思路与代码

2.1 解题思路

题目要求数组中两两数字之间第 k 小的数对距离,需求就是两个:计算数对距离、找到第 k 小个距离。那么我们就根据题目分析,数对距离的范围是在从 0 到数组最大值减数组最小值,即 [0, max(nums)-min(nums)] 这个范围上。那么我们就可以转换一下思路,将原题改成在 [0, max(nums)-min(nums)] 这个范围上寻找数组中的第 k 小数对距离。
思考到这一步之后这道题就容易多了,我们首先对数组按照从小到大进行排序,主体使用二分查找进行,在每一次计算 mid 之后,在数组中计算小于等于 mid 的数堆个数,如果大于 k ,则向左半区域继续查找;如果小于等于 k,则向右半区域继续查找,直到 left 等于 right ,最后返回 left 或 right 。
以题目示例 3 为例再对过程进行分析:
数组为 [1, 6, 1],k 为 3,此时对数组排序后数组变为 [1, 1, 6],那么我们的查找范围就是 [0, 5]


2.2 代码

class Solution {
    public int smallestDistancePair(int[] nums, int k) {
        Arrays.sort(nums);
        int left = 0;
        int right = nums[nums.length - 1] - nums[0];
        while (left < right) {
            int mid = (left + right) / 2;
            int countPairs = countPairs(nums, mid);
            if (countPairs < k) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left;
    }

    public int countPairs(int[] nums, int mid) {
        int l = 0;
        int r = 0;
        int count = 0;
        while (r < nums.length) {
            while (l < r && nums[r] - nums[l] > mid) {
                l++;
            }
            count += r - l;
            r++;
        }
        return count;
    }
}

2.3 测试结果

通过测试


测试结果

3.总结

  • 使用二分查找法在 [0, max(nums)-min(nums)] 范围上查找
  • 每次计算完 mid 便统计数组中小于等于 mid 的数对个数,如果大于 k ,则向左半区域继续查找;如果小于等于 k,则向右半区域继续查找

你可能感兴趣的:(LeetCode 每日一题——719. 找出第 K 小的数对距离)