二分法之旋转数组篇章-python

##什么是旋转数组?


输入数组:nums = [3,4,5,1,2]

原数组为 nums = [1,2,3,4,5], 旋转三次的到输入数组


输入数组:nums = [4,5,6,7,0,1,2]

原数组为 nums = [0,1,2,4,5,6,7],旋转四次得到输入数组


输入数组:nums = [2,3,8,9,10,0,1]

原数组为 nums = [0,1,2,3,8,9,10],旋转五次得到输入数组


输入数组:nums = [4,5,6,4,4,4,4]

原数组为 nums = [4,4,4,4,4,5,6],旋转五次得到输入数组

##旋转数组中元素无重复元素   

例:

输入数组:nums = [3,4,5,1,2]

原数组为 nums = [1,2,3,4,5], 旋转三次的到输入数组

##分析-我们为什么采用二分法:

我们可以清晰地认识到数组被分成两部分有序区间,我们原以为的二分方法只是单独寻找对应的元素索引值,但是在这里我们可以找到对应的区间的分界点,对应的便是该区间内部的最小值所在。

此时我们需要找到二分法所需要:

        1:所需要的与mid点进行比对的初始位置

        2:顺序存储

        3:元素有序

        4:通过下标找到关键字

        5:任取一个关键字的值即可确定所寻找的关键字是在前还是在后

##代码实现

为了便于理解这里就用if -elif-elif进行展示

def findMin(nums):
    left = 0
    right = len(nums) - 1
    if nums[0] < nums[right] :#这种判断是为了排除类似[1,2,3,4,5]这种已经排好序列的数组
        return nums[0]
    while left < right :
        mid = (left + right)//2
        if nums[mid] > nums[right] :
            left = mid + 1
        elif nums[mid] < nums[right] :
            right = mid
        else:
            left = mid + 1#大家可能会对这种情况产生疑问,这种情况说明了 最后一次循环right和left会重合在一个点便是最后的nums[right]
    return nums[right]
nums = [5,6,7,8,1]
print(findMin(nums))

        ##时间复杂度:O(log2 n)--这里只是单独用到了一个二分法将区间进行对半折开

        ##空间复杂度:O(1)--只用到了几个变量

##旋转数组中有重复元素

##分析-采用二分法的递进方法:

例:

输入数组:nums = [4,5,6,4,4,4,4]

原数组为 nums = [4,4,4,4,4,5,6],旋转五次得到输入数组

此时我们需要继续采用二分方法-但是同时我们也要注意到对应的数组中的元素变化,即我们需要考虑到重复元素带来的影响-就例如上述的nums = [4,5,6,4,4,,4,4]

对应的mid索引对应值为4,最右侧索引对应的值也为4

此时我们就需要去掉最右侧的值重新二分--只需要将右侧索引值重新赋值即可

##示例代码

def findMini(nums):
    left = 0
    right = len(nums) - 1
    while left < right :
        mid = (left + right)//2
        if nums[mid] == nums[right] :
            right -= 1#关键点便是最右侧索引号在与mid索引对应值相等是进行左移
        elif nums[mid] > nums[right] :
            left = mid + 1
        elif nums[mid] < nums[right] :
            right = mid
    return nums[right]
nums = [4,5,6,4,4,4,4]
print(findMini(nums))

        ##时间复杂度O(log2 n)=<O<=O(n){当数组中元素全部相等}

        #空间复杂度O(1)

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值