Description
Given a sorted integer array arr
, two integers k
and x
, return the k
closest integers to x
in the array. The result should also be sorted in ascending order.
An integer a
is closer to x
than an integer b
if:
|a - x| < |b - x|
, or|a - x| == |b - x|
anda < b
Example 1:
Input: arr = [1,2,3,4,5], k = 4, x = 3 Output: [1,2,3,4]
Example 2:
Input: arr = [1,2,3,4,5], k = 4, x = -1 Output: [1,2,3,4]
Constraints:
1 <= k <= arr.length
1 <= arr.length <= 104
arr
is sorted in ascending order.-104 <= arr[i], x <= 104
Code
Binary Search + Two pointer
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
int l = 0, r = arr.size();
while(l < r) {
int mid = (l + r) / 2;
if(arr[mid] < x) l = mid + 1;
else r = mid;
}
// l is now where x should be inserted
r = l;
l = l - 1;
vector<int> res;
while(l >= 0 && r < arr.size() && k) {
k--;
if(abs(arr[l] - x) <= abs(arr[r] - x)) l--;
else r++;
}
while(k) {
k--;
if(l >= 0) l--;
else if(r < arr.size()) r++;
}
for(int i = l + 1; i < r; i++) {
res.push_back(arr[i]);
}
return res;
}
};
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
vector<int> res;
int idx = lower_bound(arr.begin(), arr.end(), x) - arr.begin();
if(idx == 0) {
res.assign(arr.begin(), arr.begin() + k);
return res;
}
if(idx == arr.size()) {
res.assign(arr.end() - k, arr.end());
return res;
}
int l = idx - 1, r = idx;
while(k && (l >= 0 || r < arr.size())) {
k--;
if((l >= 0 ? abs(arr[l] - x) : INT_MAX) <= (r < arr.size() ? abs(arr[r] - x) : INT_MAX))
l--;
else
r++;
}
for(int i = l + 1; i < r; i++) {
res.push_back(arr[i]);
}
return res;
}
};
Binary Search + sliding window
Assume we are taking `A[i] ~ A[i + k - 1]`.
We can binary research `i`
We compare the distance between `x - A[mid]` and `A[mid + k] - x`
@vincent_gui listed the following cases:
Assume `A[mid] ~ A[mid + k]` is sliding window
case 1: x - A[mid] < A[mid + k] - x, need to move window go left
-------x----A[mid]-----------------A[mid + k]----------
case 2: x - A[mid] < A[mid + k] - x, need to move window go left again
-------A[mid]----x-----------------A[mid + k]----------
case 3: x - A[mid] > A[mid + k] - x, need to move window go right
-------A[mid]------------------x---A[mid + k]----------
case 4: x - A[mid] > A[mid + k] - x, need to move window go right
-------A[mid]---------------------A[mid + k]----x------
If `x - A[mid] > A[mid + k] - x`,
it means `A[mid + 1] ~ A[mid + k]` is better than `A[mid] ~ A[mid + k - 1]`,
and we have `mid` smaller than the right `i`.
So assign `left = mid + 1`.
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
int l = 0, r = arr.size() - k;
while(l < r) {
int mid = (l + r) / 2;
if(x - arr[mid] > arr[mid + k] - x) l = mid + 1;
else r = mid;
}
return vector<int>(arr.begin() + l, arr.begin() + l + k);
}
};