Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.
Example 1:
Example 2:
Note:
- The value k is positive and will always be smaller than the length of the sorted array.
- Length of the given array is positive and will not exceed 104
- Absolute value of elements in the array and x will not exceed 104
UPDATE (2017/9/19):
- The arr parameter had been changed to an array of integers (instead of a list of integers). Please reload the code definition to get the latest changes.
class Solution {
public static List<Integer> findClosestElements(int[] arr, int k, int x) {
// 思路:根据二分法找到对应的target,然后根据给定的k查询是否对半获取,优先获取比target小的数(最优的找到最后一个target)
if (arr == null || arr.length == 0) {
return new ArrayList<>();
}
int left = 0;
int right = arr.length - 1;
List<Integer> list = new ArrayList<>();
int mid = searchTargetIndex(left, right, x, arr);
findClosestNum(mid,x, k, arr, list);
return list;
}
public static int searchTargetIndex(int left, int right, int target, int[] arr) {
int mid = -1;
while (left <= right) {
mid = (left + right) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return mid;
}
public static void findClosestNum(int mid,int target, int count, int[] arr, List<Integer> list) {
// 从左右两边开始查找两数的间距,只需要k-1个
int left = mid;
int right = mid + 1;
while (count > 0) {
if (left >= 0 && right <= arr.length - 1) {
if (target - arr[left] <= arr[right] - target) {
left--;
count--;
} else {
right++;
count--;
}
} else if (left < 0 && right <= arr.length - 1) {
// 说明右边还有
right++;
count--;
} else if (left >= 0 && right > arr.length - 1) {
// 说明左边还有
left--;
count--;
}
}
// 重新确定距离
left++;
right--;
// 填充数据
for (int i = left; i <= right && left >= 0 && right <= arr.length - 1; i++) {
list.add(arr[i]);
}
}
}