给定一个排序好的数组,两个整数 k 和 x,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。如果有两个数与 x 的差值一样,优先选择数值较小的那个数。
思路:二分法查找
1、利用二分法先找到中间值,left 或 right 值是 等于x,如果数组不存在x则 两个值最接近x。
2、将left 与right 值 与x 做差进行比较,小则left – ,大则right++ 。
3、最后left + 1 到 right -1 索引 赋值给list 。(至于最后索引下标为什么是这个可以话一个数组看一下)
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
ArrayList <Integer> list = new ArrayList<Integer>();
if(arr.length == 1) {
list.add(arr[0]);
return list;
}
int left = 0, right = arr.length - 1;
int length = arr.length;
int mid = -1;
while (left + 1 < right){
mid = (left + right) / 2;
if (arr[mid] >= x){
right = mid;
}
else{
left = mid;
}
}
//从left,right处寻找与x之差的绝对值较小者
for (int i = 0; i < k; ++i){
if (left >=0 && right < length){
//取与x之差的绝对值较小者
if ((x - arr[left]) <= (arr[right] - x)){
left--;
}
else{
right++;
}
}
//否则取单边
else if (left >=0){
left--;
}
else{
right++;
}
}
for(int j = left + 1; j < right; j++){
list.add(arr[j]);
}
return list;
}
}
思路:
保留k个最近的数字,可以去掉最远的n-k个数。
观察数组 中与x最远的地方肯定是在数组两端,因此每次比较数组两端与x的差值,大的则去掉。直到数组还剩k个数字即为结果。
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
ArrayList <Integer> list = new ArrayList<Integer>();
int left = 0;
int right = arr.length - 1;
int length = arr.length - k;
while(length > 0) { //去掉相对较大的数字
if((x- arr[left]) > (arr[right] - x )) { //左边差值大于右边,左边索引 ++
left ++;
}else {
right --;
}
length --;
}
for(int i = left; i <= right; i++ ) {
list.add(arr[i]);
}
return list;
}
}