给定一个 排序好 的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。
整数 a 比整数 b 更接近 x 需要满足:
|a - x| < |b - x| 或者
|a - x| == |b - x| 且 a < b
示例 1:
输入:arr = [1,2,3,4,5], k = 4, x = 3
输出:[1,2,3,4]
示例 2:
输入:arr = [1,2,3,4,5], k = 4, x = -1
输出:[1,2,3,4]
思路1:滑动窗口双指针
使 x 尽量在 left 和 right 的中间,双指针缩小至距离为 k
x偏右,left++
x偏左,right–
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer>res=new ArrayList<>();
int left=0,right=arr.length-1;
while(right-left>=k){
if(x-arr[left]>arr[right]-x) left++;
else right--;
}
for(;left<=right;left++){
res.add(arr[left]);
}
return res;
}
}
思路2:二分
找最优区间的【左端点】,在[0, size - k]
中,使得 x 处于 arr[mid] 与 arr[mid+k] 的中间位置
如果 x 更靠近左端 arr[mid+k] ,left=mid+1;
如果 x 更靠近右端 arr[mid] ,right=mid;
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer>res=new ArrayList<>();
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;
}
for(int i=0;i<k;i++){
res.add(arr[left+i]);
}
return res;
}
}