search in rotated sorted array

Suppose an array sorted in ascending order 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.

这一题,直接遍历数组也是可以的,这是最差的一种做法,题目给的排序条件就用不上了。如果先找出旋转的位置,效果也一样,还不如直接找,都是o(n)。

因为题目说排序数组,很容易想到使用二分法。、

特点:
旋转以后,数组可以看成两部分,左边部分大于右边部分。
具体来说,假设数组是A,每次左边缘为l,右边缘为r,还有中间位置是m。在每次迭代中,分三种情况:
(1)如果target==A[mid],那么mid就是我们要的结果,直接返回;
(2)如果A[m]>=A[left],那么说明从left到mid一定是有序的(没有受到rotate的影响),那么我们只需要判断target是不是在left到mid之间,如果是则把右边缘移到m-1,否则就target在另一半,即把左边缘移到m+1。
(3)如果A[m]<A[left],那么说明从mid到right一定是有序的,同样只需要判断target是否在这个范围内,相应的移动边缘即可。

根据以上方法,每次我们都可以切掉一半的数据,所以算法的时间复杂度是O(logn),空间复杂度是O(1)。代码如下:

class Solution {
    public int search(int[] nums, int target) {
        if(nums==null||nums.length==0) return -1;
        int left=0;
        int right=nums.length-1;
        while(left<right){
            int mid=(left+right)/2;
            if(nums[mid]==target) return mid;
            //因为最终移动left和right都是根据mid的值,所以先判断mid在哪半部分,先确定mid
            //如果mid在左边..mid有可能会等于left的
            if(nums[mid]>=nums[left]){
                //如果target在left和mid中间,就移动right,若target在mid右边(可能在左半部分,也有可能在右半部分),就移动left
                if(nums[left]<=target&&nums[mid]>target)
                    right=mid-1;
                else
                    left=mid+1;
            }else{
                if(nums[right]>=target&&target>nums[mid])
                    left=mid+1;
                else
                    right=mid-1;
            }
        }
        //最后left和right重合
        return nums[left]==target?left:-1;
    }
}

 

posted on 2017-12-26 19:41  夜的第八章  阅读(136)  评论(0编辑  收藏  举报

导航