找到 K 个最接近的元素

找到 K 个最接近的元素

题目:
给定一个排序好的数组,两个整数 k 和 x,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。如果有两个数与 x 的差值一样,优先选择数值较小的那个数。

示例 1:

输入: [1,2,3,4,5], k=4, x=3
输出: [1,2,3,4]

示例 2:

输入: [1,2,3,4,5], k=4, x=-1
输出: [1,2,3,4]

解题思路: 有两种思路, 一种是运用双指针法, 通过比较左右两指针元素与x的差来缩小区间, 直到区间为k就是我们要找的区间, 还有一种思路是运用二分法来解决该问题

双指针:

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int l = 0, r = arr.length - 1;
        while(r - l + 1 > k) {
            if(Math.abs(x - arr[l]) <= Math.abs(arr[r] - x)) {
                r--;
            } else l++;
        }
        
        List<Integer> ans = new ArrayList();
        for(int i = l; i <= r; i++) {
            ans.add(arr[i]);
        }
        return ans;
    }
}

二分法: 说一下解题思路, 用二分法不断搜索离x最近的左区间,区间范围为k+1, 比较一头一尾离x的范围再来判断l和r的变化

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {        
        List<Integer> ans = new ArrayList();
        //x < 数组最小值
        if(x <= arr[0]) {
            for(int i = 0; i < k; i++) {
                ans.add(arr[i]);
            }
            return ans;
        } 
        
        //x > 数组最大值
        if(x >= arr[arr.length - 1]) {
            for(int i = arr.length - k; i < arr.length; i++) {
                ans.add(arr[i]);
            }
            return ans;
        }
        
        //l和r是区间的左边界取值, 所以r = arr.length - k - 1
        int l = 0, r = arr.length - k - 1;
        while(l <= r) {
            int mid = l + (r - l) / 2;
            // System.out.println("l = " + l + ", r = " + r);
            //从k + 1个元素里选择删除左边界还是删除右边界
            if (Math.abs(x - arr[mid]) > Math.abs(arr[mid + k] - x)) {
                //左边界离x更远所以左边界+1
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        
        // System.out.println("l = " + l + ", r = " + r);
        for(int i = l; i < l + k; i++) {
            ans.add(arr[i]);
        }
        
        return ans;
    }
}
原文地址:https://www.cnblogs.com/katoMegumi/p/13889693.html