Given a target number, a non-negative integer k and an integer array A sorted in ascending order, find the k closest numbers to target in A, sorted in ascending order by the difference between the number and target. Otherwise, sorted in ascending order by number if the difference is same.
Example
Given A = [1, 2, 3], target = 2 and k = 3, return [2, 1, 3].
Given A = [1, 4, 6, 8], target = 3 and k = 3, return [4, 1, 6].
class Solution:
# @param {int[]} A an integer array
# @param {int} target an integer
# @param {int} k a non-negative integer
# @return {int[]} an integer array
def kClosestNumbers(self, A, target, k):
if k == 0:
return []
# find target first
p, r = 0, len(A) - 1
while p + 1 < r:
q = (r - p) / 2 + p
if A[q] < target:
p = q
else:
r = q
pos = p if abs(A[p] - target) <= abs(A[r] - target) else r # 注意这里是<=
# 向左右扩展,找k个最近的
left, right = pos, pos
count = 1
ret = [A[pos]]
while count < k:
if right == len(A) - 1 or abs(A[left - 1] - target) <= abs(A[right + 1] - target): # 注意这里也是<=
left -= 1
count += 1
ret.append(A[left])
else:
right += 1
count += 1
ret.append(A[right])
return ret
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
int target = binarySearch(arr, x);
List<Integer> res = new ArrayList<>();
res.add(arr[target]);
k--;
int left = target - 1, right = target + 1;
while (k > 0) {
if (left < 0) res.add(arr[right++]);
else if (right >= arr.length) res.add(arr[left--]);
else if (Math.abs(arr[left] - x) <= Math.abs(arr[right] - x)) res.add(arr[left--]);
else res.add(arr[right++]);
k--;
}
Collections.sort(res);
return res;
}
// if target not exist, return left, if no left, return right
private int binarySearch(int[] arr, int target) {
int p = 0, r = arr.length - 1;
while (p + 1 < r) {
int q = p + (r - p) / 2;
if (arr[q] < target) p = q;
else r = q;
}
if (arr[p] == target) return p;
else if (arr[r] == target) return r;
else return p;
}
}