uacs2024

导航

leetcode 658. 找到 K 个最接近的元素

658. 找到 K 个最接近的元素

法一:

class Solution {
public:
    vector<int> findClosestElements(vector<int>& arr, int k, int x) {
        vector<pair<int,int>> dist;
        vector<int> res;
        int size = arr.size();
        for(int i = 0;i < size;++i){
            dist.emplace_back(abs(arr[i]-x),i);
        }
        sort(dist.begin(),dist.end());
        for(int i = 0;i < k;++i)  res.emplace_back(arr[dist[i].second]);
        sort(res.begin(),res.end());
        return res;
    }
};

法二:二分查找 + 双指针;不需考虑各种奇怪的边界条件,双指针会帮你判断

class Solution {
public:
//可以将数组 arr 分成两部分,前一部分所有元素 [0,left] 都小于 x,后一部分所有元素 [right,n−1] 都大于等于 x
//left 与 right 都可以通过二分查找获得。left 和 right 指向的元素都是各自部分最接近 x 的元素
//因此我们可以通过比较 left 和 right 指向的元素获取整体最接近 x 的元素
//如果 x−arr[left]≤arr[right]−x,那么将 left 减一,否则将 right 加一
//相应地,如果 left 或 right 已经越界,那么不考虑对应部分的元素。
//最后,区间 [left+1,right−1] 的元素就是我们所要获得的结果,返回答案既可。

    vector<int> findClosestElements(vector<int>& arr, int k, int x) {
        //lower_bound用于在有序区间中查找第一个大于或等于给定值的元素的位置,基于二分查找实现
        int right = lower_bound(arr.begin(), arr.end(), x) - arr.begin();
        int left = right - 1,size = arr.size();
        while(k--){
            if(left < 0)  ++right;
            else if(right >= size)  --left;
            else if(x - arr[left] <= arr[right] - x)  --left;
            else  ++right;
        }
        return vector<int>(arr.begin() + left + 1,arr.begin() + right);//表示返回[left+1,right−1]的元素
    }
};

 

posted on 2024-12-13 17:34  ᶜʸᵃⁿ  阅读(14)  评论(0)    收藏  举报