658. Find K Closest Elements(快排+折半查找)

658. Find K Closest Elements

Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.
Example1

Input: [1,2,3,4,5], k=4, x=3
Output: [1,2,3,4]

Example2

Input: [1,2,3,4,5], k=4, x=-1
Output: [1,2,3,4]

Note:

The value k is positive and will always be smaller than the length of the sorted array.
Length of the given array is positive and will not exceed 104**
Absolute value of elements in the array and x will not exceed 104

分析:

首先找到x在有序队列中的位置(使用折半查找),然后再左右移动分别找到k个距离x最近的元素,找到k个元素后,再使用快排对其进行排序。为了节省特殊情况时的计算时间,也可以先判断特殊情况,判断x是否小于有序队列的最小值,或者大于有序队列的最大值,如果是特殊情况,那么就可以直接先前或向后的k个元素即可。一下介绍两种方法。

代码如下:

class Solution {
public:
    //快速排序算法,一次循环
    int QuikeSortOnce(int* &arr,int m,int n){
    int low = m,high = n;
    int povity = arr[low];
    //cout<<low<<","<<high<<endl;
    while(low<high){
        while(low<high){
            if(arr[high]>=povity)high--;/**一定要加等于号,负责会进入死循环**/
            else{
                //cout<<"high:"<<high<<endl;
                arr[low] = arr[high];
                arr[high]=povity;
                break;
            }
        }
        while(low<high){
            if(arr[low]<=povity)low++;
            else{
                arr[high] = arr[low];
                arr[low] = povity;
                break;
            }
        }
    }
   return low;
}
//快速排序,递归调用
void QuikeSort(int *&arr,int low,int high){
    if(low<high){
        int mid = QuikeSortOnce(arr,low,high);
        QuikeSort(arr,low,mid-1);
        QuikeSort(arr,mid+1,high);
    }
}
//折半查找
    int search_bin(vector<int> arr,int key){
        int low = 0,high = arr.size()-1;
        while(low<=high){
            int mid = (low+high)/2;
            if(arr[mid]<key)low = mid+1;
            else if(arr[mid]>key)high = mid-1;
            else return mid;
        }
        return high;
    }
    vector<int> findClosestElements(vector<int>& arr, int k, int x) {
        int len = arr.size();
        vector<int> q;

        if(x>=arr[len-1]){
            int c = 1;
            while(c<=k){
                q.push_back(arr[len-1]);
                c++;
                len--;
            }
            reverse(q.begin(),q.end());
            return q;
        }else if(x<=arr[0]){
            int c = 1;
            while(c<=k){
                q.push_back(arr[c-1]);
                c++;

            }
            return q;
        }else{
            int *res;
            res = (int *)malloc(sizeof(int)*k);
            int l = search_bin(arr,x);
            int c=1;
            int low = l,high = l+1;
            while(c<=k){
                if(low>=0&&high<=len-1&&abs(x-arr[low])<=abs(x-arr[high])){

                    res[c-1] = arr[low];
                    low = low-1;
                }else if(low>=0&&high<=len-1&&abs(x-arr[low])>abs(x-arr[high])) {
                    res[c-1] = arr[high];
                    high = high+1;
                }else if(low<0){
                    res[c-1] = arr[high];
                    high = high +1;
                }else if(high>len-1){
                    res[c-1] = arr[low];
                    low = low-1;
                }
                c++;
            }
            QuikeSort(res,0,k-1);
            for(int i=0;i<k;i++)q.push_back(res[i]);
            return q;
        }

    }
};

法二:(代码精简版java)

public List<Integer> findClosestElements(List<Integer> arr, int k, int x) {
        List<Integer> ans = new ArrayList<>();
        if (arr.size() == 0) return ans;
        Collections.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                int ax = Math.abs(a - x);
                int bx = Math.abs(b - x);
                if (ax != bx) return ax - bx;
                return a - b;
            }
        });

        ans = new ArrayList<Integer>(arr.subList(0, Math.min(k, arr.size())));
        Collections.sort(ans);
        return ans;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值