力扣第719题 找出第 K 小的数对距离 二分 双指针解法 c++ 时间 超100%用户

题目

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 <= 104
  • 0 <= nums[i] <= 106
  • 1 <= k <= n * (n - 1) / 2

思路和解题方法

这段代码实现了在给定整数数组nums中找出第k小的数对距离。

  1. 首先,我们对数组nums进行排序,以便后续的二分查找能够有效进行。
  2. 然后,我们初始化最小距离left为0,最大距离right为数组最后一个元素与第一个元素的差值,也就是数组的整体范围。
  3. 使用二分查找的方法,在最小距离left和最大距离right之间进行迭代,直到leftright相等。
  4. 在每次迭代中,我们计算中间距离mid,并统计小于等于中间距离的距离对数量cnt
  5. 通过使用双指针技巧,我们在数组中遍历每个元素,并通过移动指针j来找出满足nums[j] - nums[i] <= mid的元素对。然后,我们统计距离小于等于mid的距离对数量,即j - i - 1
  6. 根据距离对数量cnt与目标k的大小关系,调整查找范围。如果cnt < k,说明第k小的数对距离应该在右半部分,因此更新left = mid + 1;如果cnt >= k,说明第k小的数对距离应该在左半部分,因此更新right = mid
  7. 最后,当leftright相等时,循环结束,最小的距离就是left,返回它即可。

总体而言,该算法通过二分查找和双指针技巧,找出了数组中第k小的数对距离。通过优化,代码变得更加简洁和高效。

复杂度

        时间复杂度:

                O(nlogn + nlogm)

时间复杂度为O(nlogn + nlogm)

  1. 对数组进行排序:使用了快速排序算法,其时间复杂度为O(nlogn)。

  2. 二分查找:每次循环都将查找范围减半,因此最多需要log₂(right - left)次迭代。在每次迭代中,需要遍历一次数组来统计距离小于等于中间距离的距离对数量。因此,对于每次迭代,时间复杂度是O(n)。

综上所述,总的时间复杂度为O(nlogn + nlogm),其中n是数组nums的长度,m是nums中的最大值和最小值的差异。

        空间复杂度

                O(1)

空间复杂度为O(1),只使用了常数级别的额外空间。

c++ 代码

 
class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
        // 对数组进行排序
        sort(nums.begin(), nums.end()); 
        // 初始化最小距离和最大距离
        int left = 0, right = nums.back() - nums.front(), n = nums.size();
        // 二分查找
        while (left < right) {
            // 计算中间距离
            int mid = left + (right - left) / 2;
            
            // 统计小于等于中间距离的距离对数量
            int cnt = 0, j = 0;
            for (int i = 0; i < n; i++) {
                // 移动指针j,使得nums[j] - nums[i] <= mid
                while (j < n && nums[j] - nums[i] <= mid) ++j;
                // 统计距离小于等于mid的距离对数量
                cnt += j - i - 1;
            }
            // 根据距离对数量与k的大小关系,不断调整范围
            if (cnt < k) left = mid + 1;
            else right = mid;
        }
        // 返回最小距离
        return left;
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

posted @   lenyan~  阅读(18)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示