33.搜索旋转排序数组(Search in Rotated Sorted Array)

33.搜索旋转排序数组 Search in Rotated Sorted Array

题解

本题看到时间复杂度需要在 O ( log ⁡ n ) O(\log n) O(logn)级别,所以想到二分查找
本题两个特殊之处

  1. 有序,可使用二分查找
  2. 旋转数组,需要找到旋转点,才能进行二分查找

二分法

算法流程:

  1. 特判:数组长度为0,返回-1. 数组长度为1,若 n u m s [ 0 ] = = t a r g e t nums[0]==target nums[0]==target,返回0,否则返回-1。(这个特例无法按照算法流程计算,所以需要单独判断)
  2. 二分法寻找旋转点:
    • 如果首元素小于尾元素,说明未旋转,返回0
    • 定义左指针 l l l和右指针 r r r,当 l < = r l<=r l<=r时,进入循环,接下来有两种写法,但是始终返回旋转点为最小值的索引
    • r o t a t e = ( l + r ) / / 2 rotate=(l+r)//2 rotate=(l+r)//2,如果 n u m s [ r o t a t e ] < n u m s [ r o t a t e − 1 ] nums[rotate]<nums[rotate-1] nums[rotate]<nums[rotate1],此时返回 r o t a t e rotate rotate,判断是否满足 n u m s [ r o t a t e ] > n u m s [ r ] nums[rotate]>nums[r] nums[rotate]>nums[r],若满足说明旋转点在右端,令 l = r o t a t e + 1 l=rotate+1 l=rotate+1,否则在左端,令 r = r o t a t e − 1 r=rotate-1 r=rotate1
    • r o t a t e = ( l + r ) / / 2 rotate=(l+r)//2 rotate=(l+r)//2,如果 n u m s [ r o t a t e ] > n u m s [ r o t a t e + 1 ] nums[rotate]>nums[rotate+1] nums[rotate]>nums[rotate+1],此时返回 r o t a t e + 1 rotate+1 rotate+1,判断是否满足 n u m s [ r o t a t e ] < n u m s [ l ] nums[rotate]<nums[l] nums[rotate]<nums[l],若满足说明旋转点在左端,令 r = r o t a t e − 1 r=rotate-1 r=rotate1,否则在右端,令 l = r o t a t e + 1 l=rotate+1 l=rotate+1
  3. 若旋转点索引 r o t a t e i n d e x = 0 rotateindex=0 rotateindex=0,说明未旋转,则直接二分查找 f i n d ( 0 , n − 1 ) find(0,n-1) find(0,n1),返回索引
  4. 判断 t a r g e t > = n u m s [ 0 ] target>=nums[0] target>=nums[0],如果满足,说明在旋转段的较大段, f i n d ( 0 , r o t a t e i n d e x ) find(0,rotateindex) find(0,rotateindex),否则 f i n d ( r o t a t e i n d e x , n − 1 ) find(rotateindex,n-1) find(rotateindex,n1)

复杂度分析

  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn)+ O ( log ⁡ n ) O(\log n) O(logn), O ( log ⁡ n ) O(\log n) O(logn)
  • 空间复杂度: O ( 1 ) O(1) O(1)

Python

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        def find_rotateindex(l,r):
            if(nums[l]<nums[r]):
                return 0
            while(l<=r):
                rotate=(l+r)//2
                if(nums[rotate]<nums[rotate-1]):
                    return rotate
                
                if(nums[rotate]>nums[r]):
                    l=rotate+1
                else:
                    r=rotate-1
        #print(find_rotateindex(0,len(nums)-1))
        def find(l,r):
            while(l<=r):
                mid=(l+r)//2
                if(nums[mid]==target):
                    return mid
                if(nums[mid]>target):
                    r=mid-1
                else:
                    l=mid+1
            return -1
        n=len(nums)
        if(n==0):
            return -1
        if(n==1):
            return 0 if(nums[0]==target) else -1
        rotateindex=find_rotateindex(0,n-1)
        if(rotateindex==0):
            return find(0,n-1)
            
        if(target>=nums[0]):
            return find(0,rotateindex)
        else:
            return find(rotateindex,n-1)

Java(待完成)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值