658. Find K Closest Elements
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]
Note:
- The value k is positive and will always be smaller than the length of the sorted array.
- Length of the given array is positive and will not exceed 10^4
- Absolute value of elements in the array and x will not exceed 10^4
方法1: heap
思路:
维持一个大小为k的heap,遍历一次数组的同时,不断踢掉距离最远的那个数。
Complexity
Time complexity: O(n + nlogk)
Space complexity: O(k)
方法2: two pointer
思路:
从两端开始,remove掉n-k个数字。每一次将双指针中距离比较远的那个消掉并移动。
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
if (arr.empty()) return {};
int left = 0, right = arr.size() - 1;
while (k < arr.size()) {
if (abs(arr[left] - x) > abs(arr[right] - x) ) {
left++;
}
else {
right--;
}
k++;
}
vector<int> result(arr.begin() + left, arr.begin() + right + 1);
return result;
}
};
// 或者原位删除
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
vector<int> res = arr;
while (res.size() > k) {
if (x - res.front() <= res.back() - x) {
res.pop_back();
} else {
res.erase(res.begin());
}
}
return res;
}
};
方法3: binary search + two pointer
思路:
先找到第一个大于或等于x的数,然后用双指针向两端扩展,直到取满k个数字。
Complexity
Time complexity: O(logn + k)
Space complexity: O(k)
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
if (arr.empty()) return {};
int left = 0, right = arr.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] >= x) {
right = mid;
}
else {
left = mid + 1;
}
}
left --;
while (k > 0) {
if (left >= 0 && right < arr.size()) {
if (abs(arr[left] - x) <= abs(arr[right] - x) ){
left--;
}
else {
right++;
}
}
else if (left >= 0) {
left--;
}
else if (right < arr.size()){
right++;
}
k--;
}
return vector<int>(arr.begin() + left + 1 , arr.begin() + right);
}
};
方法4: binary search + shrink
官方题解:https://leetcode.com/problems/find-k-closest-elements/solution/
思路:
方法5:binary search + lower bound
小Fu: https://www.youtube.com/watch?v=3ifFNvdfjyg
思路:
看看就好系列。用二分法来找到 长度为k的区间的左端点 。
class Solution {
public:
vector<int> findClosestElements(vector<int>& arr, int k, int x) {
if (arr.empty()) return {};
int left = 0, right = arr.size() - k;
while (left < right) {
int mid = left + (right - left) / 2;
if (x - arr[mid] <= arr[mid + k] - x) {
right = mid;
}
else {
left = mid + 1;
}
}
return vector<int> (arr.begin() + left, arr.begin() + left + k);
}
};