658. Find K Closest Elements
2017-08-22 本文已影响120人
DrunkPian0
找出最接近x的k个数。
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:
Input: [1,2,3,4,5], k=4, x=3
Output: [1,2,3,4]
Example 2:
Input: [1,2,3,4,5], k=4, x=-1
Output: [1,2,3,4]
这题我代码写得太长了,时间是O(n)。我看到一种新颖的解法:
public List<Integer> findClosestElements(List<Integer> arr, int k, int x) {
int lo = 0, hi = arr.size() - k;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (x - arr.get(mid) > arr.get(mid+k) - x)
lo = mid + 1;
else
hi = mid;
}
return arr.subList(lo, lo + k);
}
我的代码:
public List<Integer> findClosestElements(List<Integer> arr, int k, int x) {
//首先利用二分找到x所在的index,或者最接近x的index
//然后向左右分别搜寻k或者k-1个
if (arr == null || arr.size() == 0) return null;
if (x <= arr.get(0)) return arr.subList(0, k);
if (x >= arr.get(arr.size() - 1)) return arr.subList(arr.size() - k, arr.size());
int start = 0;
int end = arr.size() - 1;
int pivot = -1;
while (start <= end) {
int mid = start + (end - start) / 2;
if (arr.get(mid) == x) {
pivot = mid;
break;
}
if (arr.get(mid) < x) {
start = mid + 1;
} else {
end = mid - 1;
}
}
//如果没找到相同的数字
if (start > end) {
if (distanceToX(start, x, arr) < distanceToX(end, x, arr)) {
pivot = start;
} else
pivot = end;
}
List<Integer> res = new ArrayList<>();
int left = pivot - 1, right = pivot + 1;
int count = k;
while (count > 1) {
if (count == k)
res.add(arr.get(pivot));
if (distanceToX(left, x, arr) <= distanceToX(right, x, arr)) {
res.add(0, arr.get(left));
left--;
} else {
res.add(arr.get(right));
right++;
}
count--;
}
return res;
}
private int distanceToX(int idx, int x, List<Integer> arr) {
if (idx < 0 || idx >= arr.size()) {
return Integer.MAX_VALUE;
}
return Math.abs(arr.get(idx) - x);
}