描述
在一个排好序的数组 A 中找到 i 使得 A[i] 最接近 target
注意事项
There can be duplicate elements in the array, and we can return any of
the indices with same value.
样例
[1, 2, 3] target = 2, 返回 1.
[1, 4, 6] target = 3, 返回 1.
[1, 4, 6] target = 5, 返回 1 或者 2.
[1, 3, 3, 4] target = 2, 返回 0 或者 1 或者 2.
挑战
O(logn) time complexity.
代码
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 index = firstIndex(A, target);
if (index == 0) {
return 0;
}
if (index == A.length) {
return A.length - 1;
}
if (Math.abs(A[index] - target) < Math.abs(A[index - 1] - target)) {
return index;
}
return index - 1;
}
//定义一个方法,典型的二分查找模板
private int firstIndex(int[] A, int target) {
int start = 0;
int end = A.length - 1;
//二分查找
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (A[mid] == target) {
return mid;
}
if (A[mid] < target) {
start = mid;
}
if (A[mid] > target) {
end = mid;
}
}
//检查
/* 正常情况下target应该处于两个数之间,但是存在两种特殊情况,
* 一个是target小于A[0],一个是target大于A[A.length - 1]
*/
/* 在两数之间时,先返回end,然后用closestNumber代码
* 中的第三个if判断下到底end还是end - 1最接近(target不一定在
* 数组中存在,即不一定是整数,但此种情况下必在end,end - 1(即start)之间,除非target超出数组最后一个值,
* 否则不会出现target在数组中间且大于 A[end]这种情况,二分法
* 查找end不会出现这种错误思维,如果出现,证明
* 二分法没有查找定位到最后,还应该继续二分查找)
*/
if (A[end] >= target) {
return end;
}
//此为正常情况的A[start] = target和异常情况target < A[0]此时start = 0
if (A[start] >= target) {
return start;
}
//此为异常情况的target大于A[A.length - 1]
return A.length;
}
}