658J. Find K Closest Elements

https://leetcode.com/problems/find-k-closest-elements/ 这个题非常机智 Binary Search里非常机智的方法。

Method Best:

挖槽下面的答案竟然是错的,曾经通过了 其原理是下图 因此写出了如下的binary search 代码,堪称机智。

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.length - 1 - k;

        while(left <= right){
            int pivot = left + (right - left)/2;
            if(Math.abs(arr[pivot] - x) > Math.abs(arr[pivot + k] - x)){
                left = pivot + 1;
            }else{
                right = pivot - 1;
            }
        }
        // System.out.println(left);
        List<Integer> output = new ArrayList<>();
        for(int i = left; i < left + k; i++){
            output.add(arr[i]);
        }
        return output;
    }
}

正确的

这个解释也不错 [参见](https://leetcode.com/problems/find-k-closest-elements/discuss/106426/JavaC%2B%2BPython-Binary-Search-O(log(N-K)-%2B-K)) 上面的错误的原因是 比较 abs value. 事实上大致不太挫

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0;
        int right = arr.length - k - 1; 
        // 这里是 length - 1 - k 而不是 length - k, 
        // 是因为 left 可能最终是 right + 1. 所以要留足够的空间。

        while( left <= right ){
            int pivot = left + (right - left)/2;
            // 注意,这里比较的是 pivot 和 pivot + k,
            // 而这里面有 k + 1 个元素,这里的比较是在说,我们是在考虑
            // 删掉 pivot 还是 删掉 pivot + k 构成一个 k 的区间
            // 如果 pivot 的差值更大,我们觉得可以贪心一下
            // 令 left = pivot + 1, 相当于变相把它给删了
            // 如果 pivot + k 的差值更大,我们的 right = pivot - 1 也把它排除出候选范围了。
            int head = x - arr[pivot]  ;
            int tail = arr[pivot + k] - x;
            int diff = head - tail;
            if( diff == 0 ){
                right = pivot - 1;
            }else if ( diff > 0 ) {
                left = pivot + 1;
            }else{
                right = pivot - 1;
            }
        }
        List<Integer> ans = new ArrayList<>();
        for(int i = left; i < left + k; i++ ){
            ans.add(arr[i]);
        } 
        return ans;
    }
}

Last updated

Was this helpful?