1

题目: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;
    }
}

ssnau
1.5k 声望98 粉丝

负能量职业打码师


引用和评论

0 条评论