找出第k小的数对距离

数对 (a,b) 由整数 a 和 b 组成,其数对距离定义为 a 和 b 的绝对差值。
给你一个整数数组 nums 和一个整数 k ,数对由 nums[i] 和 nums[j] 组成且满足 0 <= i < j < nums.length ,返回 所有数对距离中第 k 小的数对距离。

1. 小根堆二维搜索(超时)

class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
        int n = nums.size();
        sort(nums.begin(),nums.end());
        priority_queue<tuple<int, int, int>> pq;
        pq.emplace(0, 0, 0); // 取相反数变成小顶堆
        while (!pq.empty() ){
            auto [_, i, j] = pq.top(); pq.pop();//两个数组对应下标
            if(i!=j) k--;
            if(k==0) return nums[j]-nums[i];
            if(i==j&&i+1<n)
                pq.emplace(0, i+1, j+1);
            if (j + 1 < n )//无条件移动
                pq.emplace(-(nums[j+1]-nums[i]), i, j+1);
        }
        return 0;
        }
};

2. 二分法

class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());//排序
        int n = nums.size();
        int left = 0, right = nums.back() - nums.front();//最小数对距离和最大数对距离
        while (left < right) {
            int mid = (left + right) / 2;
            int cnt = 0;
            //统计以j为右边界,距离小于等于mid 的数对个数
            for (int j = 0; j < n; j++) {
                int leftval = nums[j] - mid;//这个是区间最左侧的值
                auto leftbound = lower_bound(nums.begin(), nums.begin() + j, leftval);//获得左边界
                int i = leftbound - nums.begin();
                cnt += j - i; //右边界-左边界,获得左边界可以取得的个数,即满足条件的数对数
            }
            //
            if (cnt < k) left = mid + 1;//不满足
            else right = mid;
      
        }
        return right;
    }
};

posted @ 2023-05-29 15:28  失控D大白兔  阅读(10)  评论(0编辑  收藏  举报