题目:Search in Rotated Sorted Array Total Accepted: 11248 Total Submissions: 40041 My Submissions
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
分析:这道题看上去巨简单巨水,做起来地雷无数。各种细节判断让人防不胜防,稍有不慎便得出错误答案。已排序数组的最快搜索是二分查找,但这破题显然不能直接用二分查找,它附加了一堆曲折的判断。本来这种题目我都是一边写代码一边思考边界的,这道题写了一半代码后,觉得不少地方开始混乱了,于是不得已弄出了下面这个表格。
当数组还处于旋转状态时,即A[left] > A[right]时,下面是根据不同条件得到的不同结果:
middle = left + (right - left) / 2
No. | A[middle] < A[right] | target < A[middle] | target < A[right] | 结果 |
---|---|---|---|---|
1 | √ | √ | √ | right = middle |
2 | √ | √ | × | 不存在 |
3 | √ | × | √ | left = middle |
4 | √ | × | × | right = middle |
5 | × | √ | √ | left = middle |
6 | × | √ | × | right = middle |
7 | × | × | √ | 不存在 |
8 | × | × | × | left = middle |
当数组处于正常状态时,即A[left] < A[right],那么:
- 如果target < A[middle],则等同于上述情况1,结果为right = middle
- 如果target > A[middle],则等同于上述情况5, 结果为left = middle
由此可知,无论数组是否处于旋转状态,它的left和right的转移规则都可由上述表格来描述,于是代码照着上述表格写即可。
写这类左右逼近的代码时,有两点需要注意:
- 取两个数的平均值应当写成
middle = left + (right - left) / 2
, 而不是middle = (left + right) / 2
- 给left或right赋值是注意±1,因为如果left = 0, right = 1,那么left = middle将造成死循环。
public class Solution {
public int search(int[] A, int target) {
int left = 0;
int right = A.length - 1;
int middle = 0;
if (A.length == 0) return -1;
while(left <= right) {
middle = left + (right - left) / 2;
if (A[middle] == target) return middle;
// I don't want to deal with equal condition
// so I check them first...
if (A[right] == target) return right;
if (A[left] == target) return left;
if (A[middle] < A[right]) {
if (A[middle] < target && target < A[right]) {
left = middle + 1;
} else {
right = middle - 1;
}
} else {
if (A[middle] > target && target > A[right]) {
right = middle - 1;
} else {
left = middle + 1;
}
}
}
return -1;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。