LeetCode 33 Meidum 旋转数组中查找 Python

本文介绍了一种在旋转数组中进行二分查找的算法,详细解释了如何将查找过程分为递增区间和旋转区间,以及如何根据目标值与中间值的关系调整搜索范围。同时对比了暴力遍历和移位二分的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:

    算法:二分查找

    思路

        区间形式:

            ____↗️____|___↗️____

        把lo = mid + 1看做是选择右半段查找,hi = mid - 1看作是选择左半段查找

        即每次查找分割的时候,选择

            左:hi = mid - 1

            右:lo = mid + 1

            把区间分成递增区间和旋转区间,递增区间就是有序的区间如[1,2,3],旋转区间就是包含一段

        有序和另外一段有序的混合区间[5,6,7,1,2,3]

            查找一个数字target时,target与nums[mid]的关系只有相等,小于,大于,分别对应三种处理

        相等时返回,没的说,小于或者大于的时候,target,mid一定不是位于递增区间,就是位于旋转区间,

        或者说 mid 左侧是旋转区间or递增区间,mid右侧是旋转区间or递增区间

            则可以形式化算法为:

            if target < nums[mid]:

                [lo__target___↗️__]mid[__|___↗️____hi]

                if target >= nums[lo],即mid左侧是递增区间,target在递增区间内(nums[lo]<=target<nums[mid]):

                    在左侧查找target

                [lo___↗️__]mid[__|___↗️___target__hi]

                else 说明target 在右侧旋转区间:

                    右侧查找

                [lo____↗️___|__target__]mid[___↗️____hi]

                if  mid 左边是旋转区间,则右侧是递增区间,而taget<nums[mid],一定不去右边找

                    左侧查找,

            else 说明 target > nums[mid]

                [lo____↗️____|__]mid[__target___↗️____hi]

                if target <= nums[hi] ,即target在递增区间(nums[mid]<=target<nums[hi])

                    在右侧递增区间查找

                [lo____↗️__target___|__]mid[___↗️____hi]

                else target不在右侧递增区间内:

                    在左侧旋转区间查找

                [lo____↗️___]mid[__target___|___↗️____hi]

                if mid左边是递增区间,右侧是旋转区间,而target>nums[mid],则一定不去左边找

                    右边查找

    复杂度分析

        时间:OlogN,二分查找logN

        空间:O1,常数级

def search0( nums, target):

    lo = 0

    hi = len(nums) - 1



    while lo <= hi:

        mid = (hi+lo) // 2

        if nums[mid] == target:

            return mid

        if target < nums[mid]:

            if nums[lo] <= target or nums[mid] < nums[lo]:

                hi = mid - 1

            else:

                lo = mid + 1

        else:

            if nums[hi] >= target or nums[mid] >= nums[lo]:

                lo = mid + 1

            else:

                hi = mid - 1

    return -1

方法二:

    算法:暴力遍历

    思路:遍历一遍数组看有没有

    复杂度分析

        时间:ON,遍历一遍数组

        空间:O1,常数级

def search1(self, nums, target):

    for i in range(len(nums)):

        if nums[i] == target:

            return i

    return -1

方法三:

    算法:移位二分

    思路

            现在的列表是两端递增有序列表拼接而成,根据target大小的情况挪动lo或者hi,将lo,hi固定在一个

        正常递增的区间内再二分查找

    复杂度分析

        时间:OlogN~ON,挪lo,hi比较费时间,差一点的情况可能要ON

        空间:O1,常数级

def search2(self, nums, target):

    lo = 0

    hi = len(nums) - 1

    while lo <= hi:

        if target < nums[lo] and nums[lo] > nums[hi]:

            lo += 1

        if target > nums[hi] and nums[lo] > nums[hi]:

            hi -= 1

        if nums[lo] <= nums[hi]:

            mid = (lo + hi) // 2

            if nums[mid] == target:

                return mid

            if target < nums[mid]:

                hi = mid - 1

            else:

                lo = mid + 1

    return -1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值