题目链接
https://leetcode-cn.com/problems/find-k-closest-elements/
描述
给定一个排序好的数组,两个整数 k 和 x,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。如果有两个数与 x 的差值一样,优先选择数值较小的那个数。
说明:
k 的值为正数,且总是小于给定排序数组的长度。
数组不为空,且长度不超过 104
数组里的每个元素与 x 的绝对值不超过 104
更新(2017/9/19):
这个参数 arr 已经被改变为一个整数数组(而不是整数列表)。 请重新加载代码定义以获取最新更改。
示例
示例 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]
初始代码模板
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
}
}
代码
这个题目,相当棒!
写了半天,也就击败50%,一开始是用二分查找确定元素位置,然后再用双指针添加元素。
以下是我写的,效率并不是很高,建议直接看第二个,我是为了给自己涨个记性。
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
int xIndex = binarySearch(arr, x);
LinkedList<Integer> ans = new LinkedList<>();
int left = xIndex - 1;
int right = xIndex;
while (ans.size() < k) {
int disLeft = left >= 0 ? x - arr[left] : Integer.MAX_VALUE;
int disRight = right < arr.length ? arr[right] - x : Integer.MAX_VALUE;
if (disLeft <= disRight) {
ans.addFirst(arr[left]);
left--;
} else {
ans.add(arr[right]);
right++;
}
}
return ans;
}
private int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
right = mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
下面这个是大佬写的,可以去看看解析,写的太棒了:
https://leetcode-cn.com/problems/find-k-closest-elements/solution/pai-chu-fa-shuang-zhi-zhen-er-fen-fa-python-dai-ma/
public 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;
int mid = (left + right) >>> 1;
// 尝试从长度为 k + 1 的连续子区间删除一个元素
// 从而定位左区间端点的边界值
if (x - arr[mid] > arr[mid + k] - x) {
left = mid + 1;
} else {
right = mid;
}
}
List<Integer> res = new ArrayList<>();
for (int i = left; i < left + k; i++) {
res.add(arr[i]);
}
return res;
}
}