Idiot-maker

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

https://leetcode.com/problems/search-in-rotated-sorted-array/

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.

解题思路:

这时一道二分查找题,与标准的binary search不同,它的数组没有排序,在某个位置被rotate了。所以我们无法直接A[mid]的值和target的大小直接用mid去更新start或者end,但是一定有方法,我们来看看。

例如一个A[]:6 7 0 1 2 4 5,mid为1。如果我们要搜1,这种情况下target<A[mid],一定在前半段。如果要找比A[mid]大的,就不一定了,有可能在后半段,也有可能在被rotate到前面去的几个(6、7)里面。那么如何判断到底在前面还是后面?就看target和A[end]也就是5的大小,如果>5,一定是被rotate到前面去的,就在前面,否在在后半段。

这样就清楚了。可是写出来出错,为什么?

考虑另一个例子,A[]:2 4 5 6 7 0 1,这种情况被rotated到前面的元素多,mid为6。这时的判断就完全相反了,比A[mid]大的,一定在后半段,但是比A[mid]小的,要和A[start]比大小,然后看到底在前半段还是后半段。

这里我们可以看到,要先根据A[mid]和与[start]或者A[end]的大小来分别讨论,但是整体思路还是比较清晰的。题目不是太难。

public class Solution {
    public int search(int[] A, int target) {
        int start = 0;
        int end = A.length - 1;
        
        while(start <= end){
            int mid = (start + end) / 2;
            if(target == A[mid]){
                return mid;
            }
            if(A[mid] < A[start]){
                //后半段一定比mid大,所以这时target一定在前面
                if(target < A[mid]){
                    end = mid - 1;
                }
                //有可能在后半段,也有可能在rotate到前面的那部分
                if(target > A[mid]){
                    if(target <= A[end]){
                        start = mid + 1;
                    }else{
                        end = mid - 1;
                    }
                }
            }else{
                //前半段一定比mid小,所以这时target一定在后面
                if(target > A[mid]){
                    start = mid + 1;
                }
                if(target < A[mid]){
                    if(target < A[start]){
                        start = mid + 1;
                    }else{
                        end = mid - 1;
                    }
                }
            }
        }
        return -1;
    }
}

update 2015/07/12:

更新了代码,先判断target是不是在有序的那段,否则就在另一段

public class Solution {
    public int search(int[] nums, int target) {
        if(nums.length == 0) {
            return -1;
        }
        int start = 0, end = nums.length - 1;
        while(start <= end) {
            int mid = (start + end) / 2;
            if(nums[mid] == target) {
                return mid;
            }
            // 必须是小于等于,因为start可能等于mid
            if(nums[start] <= nums[mid]) {
                if(target < nums[mid] && target >= nums[start]) {
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            } else {
                if(target > nums[mid] && target <= nums[end]) {
                    start = mid + 1;
                } else {
                    end = mid - 1;
                }
            }
        }
        return -1;
    }
}

 

posted on 2015-03-10 14:02  NickyYe  阅读(175)  评论(0编辑  收藏  举报