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
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) { // k = 4, x = 3
if (k > arr.size() || arr.size() == 0) {
return arr;
}
if (x < arr[0]) {
return vector<int>(arr.begin(), arr.begin() + k);
} else if (x > arr[arr.size() - 1]) {
return vector<int>(arr.begin() + arr.size() - k, arr.end());
}
// Matching case.
int idx = upper_bound(arr.begin(), arr.end(), x) - arr.begin(); // idx = 2
if (idx == arr.size()) {
idx--;
}
vector<int> ans;
if (arr[idx] == x) {
// Matching and find k - 1 elements
ans.push_back(x);
find(arr, idx - 1, idx + 1, ans, k - 1, x); // left, 1, right = 3
} else {
// find k elements
find(arr, idx - 1, idx, ans, k, x);
}
sort(ans.begin(), ans.end());
return ans;
}
void find(vector<int>& arr, int left, int right, vector<int>& ans, int k, int x) {
if (k == 0) {
return;
}
while (left >= 0 || right < arr.size()) {
int left_val = (left < 0 ? INT_MAX : x - arr[left]);
int right_val = (right >= arr.size() ? INT_MAX : arr[right] - x);
if (left_val <= right_val) {
ans.push_back(arr[left]);
left--;
} else {
ans.push_back(arr[right]);
right++;
}
k--;
if (k == 0) {
return;
}
}
}
};
======== Much better and efficient ======
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
int low=0;
int high=arr.size()-1;
while(high-low+1>k){
if(abs(arr[high]-x)>=abs(arr[low]-x)){
high--;}
else
low++;
}
return vector<int>(arr.begin()+low,arr.begin()+high+1);
}
No comments:
Post a Comment