「LeetCode」719-对角线遍历

116 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

一.题目:

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

提示:

  • n == nums.length
  • 2 <= n <= 10^4
  • 0 <= nums[i] <= 10^6
  • 1 <= k <= n * (n - 1) / 2

二、思路分析:

这是一道难度为困难的题目,题目要求我们能够返回所有数对距离中第k小的数对距离,数对距离指的是从数组中选择两个元素算出他们的数组差值,而题目要求我们找到第k小的数对距离,一般遇到关键字第k小这种寻找某个位置的题目的时候,都会用到二分法,如果单单采取枚举的方法算出每两个元素的值在进行比较就一定会超时。本题的基本步骤为:

  • 我们首先确定范围,先将数组进行单调递增的排序,目的是寻找最小和最大距离值。
  • 随后确定范围,即在哪个范围寻找到目标距离,最小的距离则是0,因为可能有重复值,最大的距离则是数组中的最大值减去数组中的最小值。
  • 利用二分法找到中间值,然后利用双指针遍历数组,从数组中找寻小于这个中间值mid的数对距离数量,随后利用这个结果与k进行比较,如果大于等于k值就需要调整right值,反之调整left值,最终得出结果。

三、代码:

function smallestDistancePair(nums: number[], k: number): number {
    const numCount = (mid):number => {
        let count = 0;
        for(let i = 0, j = 0 ; j < nums.length ; j++){
            while(nums[j] - nums[i] > mid){
                i++
            }
            count += j - i;
        }
        return count
    }
    nums.sort((a,b) => a - b);
    let left = 0, right = nums[nums.length - 1] - nums[0];
    while(left < right){
        const mid = (left + right) >> 1;
        if(numCount(mid) >= k){
            right = mid;
        }else{
            left = mid + 1;
        }
    }
    return left;
};

四、总结:

这道题看着简单但是利用到了三个知识点的运用:数组排序二分法双指针的运用,很考验掌握知识的全面性,当然做好这道题也要很细心,要记住平时二分法容易出错的地方。