给定一个排序好的数组,两个整数 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]
说明:
k 的值为正数,且总是小于给定排序数组的长度。
数组不为空,且长度不超过 10^4
数组里的每个元素与 x 的绝对值不超过 10^4
思路:
由于数组有序,所以最后找到的k个元素也一定是有序的,其实就是返回了一个长度为k的子数组,相当于在长度为n的数组中去掉n-k个数字, 而且去掉的顺序肯定是从两头开始去,因为距离x最远的数字肯定在首尾出现。每次比较首尾两个数字跟x的距离,将距离大的那个数字删除,直到剩余的数组长度为k为止。
//留下最近的 也就是去掉最远的 直到数组长度为k
public List<Integer> findClosestElements1(int[] arr, int k, int x) {
List<Integer> res=new ArrayList<>();
int len=arr.length;
int left=0;
int right=len-1;
while (len>k) {
if (Math.abs(arr[left]-x)>Math.abs(arr[right]-x)) {
left++;
}else {
right--;
}
len--;
}
for (int index = left; index <=right; index++) {
res.add(arr[index]);
}
return res;
}
还可以利用二分的方法 找到距离最近区间的起点
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> res = new ArrayList<>();
int start = 0, end = arr.length-k;
while(start<end){
int mid = start + (end-start)/2;
if(Math.abs(arr[mid]-x)>Math.abs(arr[mid+k]-x)){ //中位数距离x比较远 所以看右半部分
start = mid+1;
} else {
end = mid;
}
}
for(int i=start; i<start+k; i++){
res.add(arr[i]);
}
return res;
}