You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
public int searchInsert(int[] A, int target) {
int left = 0;
int right = A.length - 1;
int mid;
if (target < A[0]) {
return 0;
}
if (target > A[A.length - 1]) {
return A.length;
}
// find the last number less than target
while (left + 1 < right) {
mid = left + (right - left) / 2;
if (A[mid] == target) {
return mid;
} else if (A[mid] < target) {
left = mid;
} else {
right= mid;
}
}
if (target == A[left]) {
return left;
}
if (target == A[right]) {
return right;
}
return left + 1;
}
首先是使用了下面这个 binary search 模板
while (left + 1 < right) {
mid = left + (right - left) / 2;
if (A[mid] == target) {
return mid;
} else if (A[mid] < target) {
left = mid;
} else {
right= mid;
}
}
if (target == A[left]) {
// ...
}
if (target == A[right]) {
// ...
}
这个模板和普通 binary search 有个不同之处就是 while 循环的判断条件是: while (left + 1 < right)
也就是说,在这种判断条件下,当left index 和 right index 相邻时 (left + 1 == right),循环就会跳出。这个时候,left 和 right 对应的值肯定有一个还没有与 target 比较过。例如,如果上一次循环是 left = mid, 则当前的 right 还没有和 target 比较过。反过来,如果上次循环是 right = mid, 则当前的 left 还没有和 target 比较过。
另外一个不同之处就是: left = mid 和 right = mid, 而不是 left = mid + 1 和 right = mid - 1. 这是为了保证在跳出时 left 和 right 是相邻一位的。如果是常规写法,跳出时 left 和 right 重合
明确了这种写法在 left + 1 == right(相邻一位) 跳出后,再看针对这一题如何思考。首先:
if (target < A[0]) {
return 0;
}
if (target > A[A.length - 1]) {
return A.length;
}
确保了这两个特殊情况。
如果没有遇上两个特殊情况,则先进去循环,再跳出循环,此时 left 和 right 相邻一位。此时有3种可能:
target == A[left]
target == A[right]
target在 left 和 right 之间 --- > return left + 1