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

来源:互联网 发布:杭州sql培训班 编辑:程序博客网 时间:2024/06/09 11:54

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;    }
原创粉丝点击