问题描述:
在一个排好序的数组 A 中找到 i 使得 A[i] 最接近 target
解法一:
思路:
Naive二分查找,如果找到target就返回。出循环后,找到最近的那个边界。
###Code:
public class Solution {
/**
* @param A an integer array sorted in ascending order
* @param target an integer
* @return an integer
*/
public int closestNumber(int[] A, int target) {
if (A == null || A.length == 0){
return -1;
}
int start = 0, end = A.length - 1;
while (start + 1 < end){
int mid = start + (end - start) /2;
if (A[mid] == target){
return mid;
}
else if (A[mid] > target){
end = mid;
}
else{
start = mid;
}
}
if (Math.abs(A[start] - target) <= Math.abs(A[end] - target)){
return start;
}
else{
return end;
}
}
}
解法二:
思路:
同样是二分查找,构建二分查找的目标为数组中第一次大于等于target的位置辅助函数firstIndex()….
主循环中进行case 判断
nums[index - 1] << target << nums[index]
Code:
public class Solution {
/**
* @param A an integer array
* @param target an integer
* @param k a non-negative integer
* @return an integer array
*/
public int[] kClosestNumbers(int[] A, int target, int k) {
// Write your code here
int[] res = new int[k];
if (A == null || A.length == 0){
return A;
}
if (A.length < k){
return A;
}
int index = firstIndex(A, target);
int start = index - 1;
int end = index;
for (int i = 0; i < k; i++){
if (start < 0) {
res[i] = A[end++];
} else if (end >= A.length) {
res[i] = A[start--];
} else {
if (target - A[start] <= A[end] - target){
res[i] = A[start--];
} else {
res[i] = A[end++];
}
}
}
return res;
}
// 在数组中找第一个大于等于target的index
private int firstIndex(int[] nums, int target) {
int start = 0;
int end = nums.length - 1;
while (start + 1 < end) {
int mid = (end - start) / 2 + start;
if (nums[mid] == target) {
end = mid;
} else if (nums[mid] > target) {
end = mid;
} else {
start = mid;
}
}
if (nums[start] >= target){
return start;
}
if (nums[end] >= target) {
return end;
}
return nums.length;
}
}
评注:
代码虽然啰嗦,但是这种方法在找到排序数组中找最接近的K个数 的题目中非常有用,值得借鉴。