My PriorityQueue solution, the time complexity is O(n+klog(k)) = O(nlog(n)).

    class IndexDistance{
        int index;
        int distance;
        public IndexDistance(int a, int b){
            this.index = a;
            this.distance = b;
        }
    }
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        PriorityQueue<IndexDistance> pq = new PriorityQueue<>((a,b)->a.distance==b.distance?a.index-b.index:a.distance-b.distance);
        int n = arr.length;
        int[] distances = new int[n];
        for(int i=0;i<arr.length;i++){
            distances[i]=Math.abs(arr[i]-x);
            pq.offer(new IndexDistance(i, distances[i]));
        }
        List<Integer> res = new ArrayList<>();
        for(int i=0;i<k;i++){
            res.add(arr[pq.poll().index]);
        }
        Collections.sort(res);
        return res;
    }

The Binary Search Solution, the mid ~ mid+k is a sliding widonw, they have 4 conditions with x:

1.  x...arr[mid]...arr[mid+k]     x-arr[mid]<arr[mid+k]-x -> right=mid 

2. arr[mid]...x......arr[mid+k]   x-arr[mid]<arr[mid+k]-x -> right=mid 

3. arr[mid]......x...arr[mid+k]   x-arr[mid]>. arr[mid+k]-x  left=mid +1

4. arr[mid]...arr[mid+k]...x     x-arr[mid]>. arr[mid+k]-x  left=mid +1

At last, left = right, the window left ~ left+k is the result.

    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.length - k;
        while (left < right) {
            int mid = (left + right) / 2;
            if (x - arr[mid] > arr[mid + k] - x)
                left = mid + 1;
            else
                right = mid;
        }
        List<Integer> res = new ArrayList<>();
        for(int i=left;i<left+k;i++){
            res.add(arr[i]);
        }
        return res;       
    }

 

posted on 2022-02-10 09:13  阳光明媚的菲越  阅读(18)  评论(0编辑  收藏  举报