[leetCode]658. 找到 K 个最接近的元素

这篇博客介绍了如何利用双指针和二分查找算法解决LeetCode上的找最近k个元素的问题。文章详细阐述了两种方法的实现思路:双指针法从数组两端开始比较,逐步缩小范围;二分查找法通过不断调整区间找到最优左边界。两种方法都针对已排序数组,确保找到与目标值x最接近的k个元素。
摘要由CSDN通过智能技术生成

题目

https://leetcode-cn.com/problems/find-k-closest-elements/

在这里插入图片描述

双指针

数组是排序的,使用双指针指向数组两端,如果一端离x更远就排除该指针指向的元素,如果一样远,根据题意排除右指针指向的元素

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

二分查找

思路:
查找最优区间的左边界,sizearr的长度, 由于要保证区间内有k个元素所以,搜索范围为[0, size - k]left = 0, right = size - k
以中值mid为左边界开辟一个长度为k+1的区间[mid, mid + k]
对于 x 分情况讨论

  1. x 在区间 [mid, mid + k]

    • x在[mid, mid + k]左边,则需要使整个区间向左移动, 所以 right = mid
    • x在[mid, mid + k]右边, 则整个区间需要向右移动,所以left = mid + 1
  2. x 在区间[mid, mid + k]

    • x在区间中间,或者x更靠近arr[mid],整个区间需要向左移动,right = mid
    • x更接近arr[mid + k],整个区间需要向右移动,left = mid + 1

综上情况1.1 和 2.1、1.2 和 2.2 可以合并,也就是下面这段代码

if (x - arr[mid] > arr[mid + k] - x) {
    left = mid + 1;
} else {
    right = mid;
}
class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int size = arr.length;
        int left = 0;
        int right = size - k;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (x - arr[mid] > arr[mid + k] - x) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        List<Integer>ans = new ArrayList<>();
        for (int i = left;i < k + left; i++) {
            ans.add(arr[i]);
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值