LeetCode 33.搜索旋转排序数组

Posted KyrieLiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 33.搜索旋转排序数组相关的知识,希望对你有一定的参考价值。

解法一:顺序查找

时间复杂度:O(n)

int search(vector<int>& nums, int target) {
    for(int i=0;i<nums.size();i++){
        if(nums[i]==target) return i;
    }
    return -1;
}

解法二:二分查找

分析:

题目进阶中,要求设计一个O(logn)的方案,根据时间复杂度,在查找方案中很容易想到二分查找。

但与正常的二分查找不同,该数组是在某个下标 k 下进行了旋转,因此,在二分查找时,需要做一些特定的处理。

假设数组旋转之前为:【0 1 2 4 5 6 7】

旋转之后可能是(k=3):【4 5 6 7 0 1 2】

普通的二分查找:

前提:有序序列

将待查找序列根据中间元素 mid ,将序列划分为 [low,mid-1]mid[mid+1,high]

  • 如果待查找元素 target==nums[mid],代表查找成功,返回 mid
  • 如果 target < nums[mid],则在左半部分 [low,mid-1]继续二分查找
  • 如果 target > nums[mid],则在右半部分 [mid+1,high]继续二分查找

直到找到与target相等元素的位置,或发现序列中不存在与target相等的值

时间复杂度:O(logn)

普通二分查找的代码:

//普通二分 
int binarySearch(vector<int>& nums, int target){
    if(nums.size()==0) return -1;
    int low=0,high=nums.size()-1;
    while(low<=high){
        int mid = low + (high-low)/2; //避免low+high越界 
        if(nums[mid]==target) return mid;
        else if(nums[mid]<target) low=mid+1;
        else high=mid-1;
    } 
    //结束条件:low>high 
    return -1;
}

经过旋转后的数组,只是局部有序,整体并不有序,那么本题如何应用二分?

与普通的二分查找一样,根据中间元素 mid ,将序列划分为 [low,mid-1]mid[mid+1,high]

不同的是,在比较targetnums[mid] 之前,先比较 nums[low]nums[mid] 的关系,原理如下:

第一类序列:【2 3 4 5 6 7 1】,也就是 nums[low] < nums[mid] ,此例中为2<5。这种情况下,可以保证序列的前半部分是有序的。

  • 如果 nums[low] <= target < nums[mid] ,则去前半部分找
  • 否则,去后半部分找

第二类序列:【6 7 1 2 3 4 5】,也就是 nums[low] > nums[mid] ,此例中为6>2。这种情况下,可以保证序列的后半部分是有序的。

  • 如果 nums[mid] <= target < nums[end] ,则去后半部分找
  • 否则,去前半部分找

代码:

int rotateBinarySearch(vector<int>& nums, int target){
    if(nums.size()==0) return -1;
    int low=0,high=nums.size()-1;
    while(low<=high){
        int mid = low+(high-low)/2;
        if(nums[mid]==target) return mid;
        else if(nums[low]<=nums[mid]){  //下面两个if中 target一定不等于 nums[mid],因为是从上面的if过来的 
            if(nums[low]<=target && target<nums[mid]){ //mid\'s left 
                high=mid-1;
            }else { //mid\'s right
                low=mid+1;
            }
        }else { //nums[low]>nums[mid]
            if(nums[mid]<target && target<=nums[high]){ //right
                low=mid+1;
            }else { //left
                high = mid-1;
            }
        }
    } 

    return -1;
} 

以上是关于LeetCode 33.搜索旋转排序数组的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode33. 搜索旋转排序数组

Leetcode 33.搜索旋转排序数组

[leetcode] 33. 搜索旋转排序数组(Java)

leetcode[33. 搜索旋转排序数组]

LeetCode 33 搜索旋转排序数组

5-002-(LeetCode- 33) 搜索旋转排序数组