版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tc_To_Top/article/details/82150311
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 104
- Absolute value of elements in the array and x will not exceed 104
题目链接:https://leetcode.com/problems/find-k-closest-elements/description/
题目分析:
方法一:二分大于x的第一个数,然后two point,时间复杂度(2k+logn)
class Solution {
public boolean smallerOrEq(int lval, int rval, int x) {
return Math.abs(lval - x) <= Math.abs(rval - x);
}
public int upperBound(int[] arr, int n, int x) {
int l = 0, r = n - 1, mid = 0, ans = 0;
if (x <= arr[l]) {
return l;
}
if (x >= arr[r]) {
return r;
}
while (l <= r) {
mid = (l + r) >> 1;
if (arr[mid] <= x) {
l = mid + 1;
} else {
ans = mid;
r = mid - 1;
}
}
return ans;
}
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> ans = new ArrayList<>();
int upperPos = upperBound(arr, arr.length, x);
int l = upperPos, r = upperPos;
while (r - l < k) {
if (l > 0 && r < arr.length) {
if (smallerOrEq(arr[l - 1], arr[r], x)) {
l--;
} else {
r++;
}
} else if (l == 0) {
r++;
} else {
l--;
}
}
for (int i = l; i < l + k; i++) {
ans.add(arr[i]);
}
return ans;
}
}
方法二:直接一次二分,考虑x, arr[mid]和arr[mid+k]这三个值的大小关系,分三种情况
1)arr[mid] <= arr[mid+k] <= x(mid右移)
2)x <= arr[mid] <= arr[mid+k](mid左移)
3)arr[mid] <= x <= arr[mid+k] => arr[mid+k] - x < x - arr[mid](mid右移);arr[mid+k] - x >= x - arr[mid](mid左移)
容易发现3)的两种情况的移动方向恰好与1)2)一致,因此可以直接二分左边界,时间复杂度(k+logn)
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> ans = new ArrayList<>();
int l = 0, r = arr.length - k - 1, mid;
while (l <= r) {
mid = (l + r) >> 1;
if (Math.abs(arr[mid + k] - x) >= Math.abs(x - arr[mid])) {
r = mid - 1;
} else {
l = mid + 1;
}
}
for (int i = l; i < l + k; i++) {
ans.add(arr[i]);
}
return ans;
}
}