力扣_数组9—搜索旋转排序数组

题目

  • 旋转排序数组:将严格单调递增数组 [ k , n − 1 ] [k,n-1] [k,n1] 的子序列放到开头。例如, [ 0 , 1 , 2 , 4 , 5 , 6 , 7 ] [0,1,2,4,5,6,7] [0,1,2,4,5,6,7] 在下标 3 3 3 处经旋转后可能变为 [ 4 , 5 , 6 , 7 , 0 , 1 , 2 ] [4,5,6,7,0,1,2] [4,5,6,7,0,1,2].
  • 要求以 O ( l o g N ) O(logN) O(logN) 的复杂度返回旋转排序后的数组中值为 t a r g e t target target 的索引,没有则返回 − 1 -1 1.

关键点

  • O ( l o g N ) O(logN) O(logN) 复杂度(二分查找)、
  • 旋转排序后的数组如何进行二分查找

思路

  • 正常使用二分查找,关键在于如何更新查找区间的左右边界
  • 对于正常的有序数组(假设递增),初始化左右边界 p l , p r pl,pr pl,pr 0 , n − 1 0, n-1 0,n1。判断 m i d = i n t ( ( p l + p r ) / 2 ) mid=int((pl+pr)/2) mid=int((pl+pr)/2) t a r g e t target target 的大小关系:
    • n u m s [ m i d ] = = t a r g e t , r e t u r n nums[mid] == target, return nums[mid]==target,return
    • n u m s [ m i d ] < t a r g e t , p l = m i d + 1 nums[mid] < target, pl=mid+1 nums[mid]<target,pl=mid+1
    • n u m s [ m i d ] > t a r g e t , p r = m i d − 1 nums[mid] > target, pr=mid-1 nums[mid]>target,pr=mid1
  • 对于本题的旋转排序数组,初始化左右边界 p l , p r pl,pr pl,pr 0 , n − 1 0, n-1 0,n1 m i d = i n t ( ( p l + p r ) / 2 ) mid=int((pl+pr)/2) mid=int((pl+pr)/2) m i d mid mid p l pl pl p r pr pr 的数组分为了两半,其中必有一半是有序的:
    • [ p l , m i d ] [pl, mid] [pl,mid] 有序:
      • t a r g e t target target [ p l , m i d ] [pl, mid] [pl,mid] 中, p r = m i d − 1 pr=mid-1 pr=mid1
      • 若不在, p l = m i d + 1 pl=mid+1 pl=mid+1
    • [ m i d , p r ] [mid, pr] [mid,pr] 有序:
      • t a r g e t target target [ m i d , p r ] [mid, pr] [mid,pr] 中, p l = m i d + 1 pl=mid+1 pl=mid+1
      • 若不在, p r = m i d − 1 pr=mid-1 pr=mid1
  • 如何判断 [ p l , m i d ] [pl,mid] [pl,mid] [ m i d , p r ] [mid,pr] [mid,pr] 哪个有序
    • 比较 n u m s [ m i d ] nums[mid] nums[mid] n u m s [ 0 ] nums[0] nums[0] 的大小
      • n u m s [ 0 ] < n u m s [ m i d ] nums[0] < nums[mid] nums[0]<nums[mid] [ 0 , m i d ] [0, mid] [0,mid] 必定有序,进而可以得到 [ p l , m i d ] [pl, mid] [pl,mid] 必定有序
      • n u m s [ 0 ] > n u m s [ m i d ] nums[0] > nums[mid] nums[0]>nums[mid] [ 0 , m i d ] [0, mid] [0,mid] 必定无序,进而可以得到 [ m i d , n − 1 ] [mid, n-1] [mid,n1] 必定有序,进一步得到 [ m i d , p r ] [mid, pr] [mid,pr] 必定有序

代码

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // O(N)
        // int n = nums.size();
        // for(int i = 0; i < n; i++){
        //     if(nums[i] == target){
        //         return i;
        //     }
        // }
        // return -1;

        // O(logN)
        int n = nums.size();
        int pl = 0, pr = n-1;
        while(pl <= pr && pl >= 0 && pr <= n-1){
            int mid = (pl+pr)/2;
            if(nums[mid] == target){
                return mid;
            }
            if(nums[mid] >= nums[0]){
                if(nums[0] <= target && target < nums[mid]){
                    pr = mid - 1;
                }
                else{
                    pl = mid + 1;
                }
            }
            else{
                if(nums[mid] < target && target <= nums[pr]){
                    pl = mid + 1;
                }
                else{
                    pr = mid - 1;
                }
            }
        }
        return -1;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值