[LeetCode]33. Search in Rotated Sorted Array

33. 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.

分析

题中给出的序列是由两个已经排序的序列合并而成的,并且后面的有序序列的所有数都是比第一个序列的首元素小,这里有两种思路:

  1. 找到这个pivot所在的位置,然后用target和这个pivot所在元素比较,找出target在前半段还是后半段范围内,然后在这个找到的范围内用二分法查找

  2. 直接使用二分查找法,只是这里的二分法稍微复杂了点。
    如果nums[first] <= nums[mid],那么firstmid之间是有序的,这个时候判断target是否在first...mid之间,在的话last=mid,如果不在,那肯定在mid+1...last之间,first=mid+1;
    否则nums[first] > nums[mid],那么pivot在first…mid之间,即mid…last之间是有序的,这个时候判断target是否在mid...last之间,在的话first=mid+1,如果不在,那肯定在first...mid之间,last=mid

源码

方法1:先找pivot,然后用二分法

    int binarySearch(vector<int>& nums, int start, int end, int target) {

        // 递归二分法
        // if((end - start) == 1 || end == start) {
        //     if(nums[start] == target) return start;
        //     else if(nums[end] == target) return end;
        //     else return -1;
        // }

        // int middle = (end + start) / 2;
        // if(nums[middle] == target) return middle;
        // else if(nums[middle] < target) start = middle;
        // else end = middle;

        // return binarySearch(nums,start,end,target);

        //循环二分法
        int middle, low = start, high = end;
        int ret = -1;
        while(low <= high) {
            middle = (low + high) / 2;
            if(nums[middle] == target) {
                ret = middle;
                break;
            } else if(nums[middle] < target) {
                low = middle + 1;
            } else {
                high = middle - 1;
            }
        }
        return ret;
    }

    //寻找pivot
    int indexOfPivot(vector<int>& nums) {
        int index = -1;

        if(nums.size() < 2) return index;

        for(int i = 1; i < nums.size(); i++) {
            if(nums[i] < nums[i-1]) {//当前数比前一数小,因为没有重复数,所以可以直接判断
                index = i;
                break;
            }
        }

        return index;
    }

    int search(vector<int>& nums, int target) {
        if(nums.size() == 0) return -1;
        int pivot = indexOfPivot(nums);
        if(pivot == -1) return binarySearch(nums, 0, nums.size() - 1, target);//没有pivot,直接二分法
        else if(nums[pivot] <= target && target <= nums[nums.size()-1]) return binarySearch(nums,pivot,nums.size() - 1, target);
        else if(nums[pivot - 1] >= target) return binarySearch(nums,0,pivot - 1, target);
        else return -1;
    }

方法二:直接二分法

    int search(const vector<int>& nums, int target) {
        int first = 0, last = nums.size();
        while (first != last) {
            const int mid = first + (last - first) / 2;
            if (nums[mid] == target)
                return mid;
            if (nums[first] <= nums[mid]) { // 因为序列没有重复元素,这里等号不需要也可以; first...mid之间都是顺序的
                if (nums[first] <= target && target < nums[mid])
                    last = mid;
                else
                    first = mid + 1;
            } else { // nums[first] > nums[mid] 说明序列扭转点发生在first...mid之间,但是mid之后的数是顺序的
                if (nums[mid] < target && target <= nums[last-1])
                    first = mid + 1;
                else
                    last = mid;
            }
        }
        return -1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值