题目地址:
https://leetcode.com/problems/find-k-closest-elements/
在一个长 n n n的升序数组 A A A中(不一定严格升序),返回距离某数 x x x最近的 k k k个数。数据保证数组长度大于 k k k。
思路是二分。我们可以对这 k k k个数的左端点的下标做二分。若数组长度为 l l l,那么这个左端点的范围就是 [ 0 , l − k ] [0, l-k] [0,l−k]。对于每个分点 m m m,我们考虑 x − A [ m ] x-A[m] x−A[m]和 A [ m + k ] − x A[m+k]-x A[m+k]−x哪个小,如果前者小或者一样小,那么向右找只能找到更差的解,但是注意到题目要求如果有一样近的则取较小的,所以如果两个一样小,说明 x x x正好夹在两个端点正中间,当前所选的区间有可能是最终解,所以移动范围的右端点到 m m m,否则移动范围的左端点到 m + 1 m+1 m+1。如此这般,直到分出结果。代码如下:
class Solution {
public:
vector<int> findClosestElements(vector<int>& a, int k, int x) {
vector<int> res;
int l = 0, r = a.size() - k;
while (l < r) {
int mid = l + (r - l >> 1);
if (x - a[mid] <= a[mid + k] - x) r = mid;
else l = mid + 1;
}
return vector<int>(a.begin() + l, a.begin() + l + k);
}
};
时间复杂度 O ( log ( n − k ) + k ) O(\log (n-k)+k) O(log(n−k)+k), n n n是数组长度,空间 O ( 1 ) O(1) O(1)。