【leetcode-Python】-二分搜索-81 Search in Rotated Sorted Array II

目录

 

题目链接

题目描述

示例

解决思路一

解决思路一Python实现

解决思路二

解决思路二Python代码

 相关题目


题目链接

81. Search in Rotated Sorted Array II

题目描述

在可能包含重复元素的旋转有序数组中搜索一个target,如果target在数组中被找到,返回True,否则返回False。

示例

输入:nums=[2,5,6,0,0,1,2], target = 0

输出:True

输入:nums=[2,5,6,0,0,1,2], target = 3

输出:False

解决思路一

1、在有重复元素的旋转有序数组中找到旋转点pivot,即第一个小于nums[-1]的元素(可参考【leetcode-Python】- 二分搜索 - 154 Find Minimum in Rotated Sorted Array II中的“进一步扩展”部分)。

2、比较target和nums[-1]的大小,如果target小于nums[-1],说明target在右排序数组中,下一步在[pivot,len(nums)-1]范围内搜索target;如果target大于nums[-1],说明target在左排序数组中,下一步在[0,pivot-1]范围内进行搜索,搜索过程可参考模板一【Leetcode-Python】-二分搜索模板汇总与相关题目。如果target等于nums[-1],说明target一定可以在nums中找到,因此直接返回True。

时间复杂度:最优情况下(数组中所有元素都不相等)时间复杂度为O(logN),最差情况下(数组元素都相等并且不等于target)时间复杂度为O(N)

空间复杂度:O(1)

解决思路一Python实现

class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        if(len(nums) == 0):
            return False
        # get the pivot
        left = 0
        right = len(nums)-1
        while(left < right):
            mid = (left + right) // 2
            if(nums[mid] > nums[right]): #说明pivot在mid的右侧,且mid不可能是pivot
                left = mid + 1    
            elif(nums[mid] < nums[right]) : #pivot有可能是mid,也可能在mid 的左侧。
                right = mid
            else: # nums[mid] == nums[right] #pivot不确定在mid的左侧还是右侧。
                if(nums[right] < nums[right - 1]): #在这个条件下nums[right]就是pivot,如果不做这一步判断直接通过right -= 1缩小范围的话有可能把pivot越过。
                    break #跳出循环
                right -= 1 #如果nums[right]不是pivot,需要将right向左移动一位,缩小搜索范围。
        pivot = right
        if(target > nums[-1]): #target可能在左排序序列
            left,right = 0,pivot-1
        elif(target < nums[-1]): #target可能在右排序序列
            left,right = pivot,len(nums)-1
        else:
            return True
        while(left <= right): #这一部分参考模板一
            mid = (left + right) // 2
            if(nums[mid] == target):
                return True
            elif(nums[mid] < target):
                left = mid + 1
            else:
                right = mid - 1
        return False
            
        
                

解决思路二

总体上仍然采用二分搜索的思路,但和上一个思路还是有些差别:在这个方法中,直接根据nums[mid]和target在旋转有序数组中的位置(左排序序列还是右排序序列)来收缩搜索区间,不需要先判断旋转点的位置。考虑循环的维持条件、搜索区间收缩的条件和边界的更新方式这几个写二分搜索时要注意的关键点,由于是在数组中寻找某元素是否存在,优先考虑模板一,模板详见【Leetcode-Python】-二分搜索模板汇总与相关题目。循环的维持条件为left <= right,对应边界更新方式是left = mid + 1或right = mid - 1。搜索区间收缩条件根据nums[mid]和target在旋转有序数组中的位置确定,nums[mid]和target(如果存在)在旋转有序数组中的位置包括三种情况:

(1)nums[mid]在左排序序列(nums[mid] > nums[right]),target在右排序序列中存在(target <= nums[right])。这种情况下更新left = mid + 1。

(2)nums[mid]在右排序序列(nums[mid] < nums[right]),target在左排序序列中存在(target > nums[right])。这种情况下更新right = mid - 1。

(3)target和nums[mid]同时在左排序序列或右排序序列。  由于两个序列都是升序序列,这种情况下根据target和nums[mid]的大小比较结果来收缩搜索区间。

在情况(2)中,由于target > nums[right],因此target不可能在右排序序列中存在,那么如果target存在,只会在左排序序列中存在。其次认为target == nums[right]属于target在右排序序列的情况,不一定能够保证target在左排序序列中一定存在。因此在第二种情况中“target在左排序序列中存在”的代码表达为target > nums[right]。

当nums[mid] == nums[right]时不确定nums[mid]在左排序序列还是在右排序序列,此时令right -= 1缩小搜索范围,在不影响搜索结果的条件下继续循环。

时间复杂度:最优情况下(数组中所有元素都不相等)时间复杂度为O(logN),最差情况下(数组元素都相等并且不等于target)时间复杂度为O(N)

空间复杂度:O(1)

但是当nums中元素非常多时,解决思路二相较于解决思路一要快一些,因为解决思路一需要先寻找pivot再缩小搜索区间,解决思路二则略过了寻找pivot这一步。

解决思路二Python代码

class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        if(len(nums) == 0):
            return False
        left = 0
        right = len(nums)-1
        while(left <= right):
            mid = (left + right) // 2
            if(nums[mid] == target): 
                return True
            if(nums[mid] == nums[right]):#如果nums[mid] == nums[right],不确定nums[mid]在左排序区间还是右排序区间,在这种情况下让right左移一位以在不影响结果的前提下继续循环
                right -= 1
                continue
            if(nums[mid] > nums[right] and target <= nums[right]):#nums[mid]在左排序序列 并且 target在右排序序列(如果target < nums[right],target在右排序序列,如果target == nums[right],target也在右排序序列,这里两种情况放到一起考虑,
#因为收缩搜索区间的方式都是left = mid + 1)
                left = mid + 1
            elif(nums[mid] < nums[right] and target > nums[right]): #nums[mid]在右排序序列,target在左排序序列
                right = mid - 1
            else: #target和nums[mid]同时在左排序序列或右排序序列,但两个子序列都是升序序列
                if(target > nums[mid]):
                    left = mid + 1
                else:
                    right = mid - 1
        return False

        

 

 相关题目

【leetcode-Python】- 二分搜索 - 154 Find Minimum in Rotated Sorted Array II

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码下载:完整代码,可直接运行 ;运行版本:2022a或2019b或2014a;若运行有问题,可私信博主; **仿真咨询 1 各类智能优化算法改进及应用** 生产调度、经济调度、装配线调度、充电优化、车间调度、发车优化、水库调度、三维装箱、物流选址、货位优化、公交排班优化、充电桩布局优化、车间布局优化、集装箱船配载优化、水泵组合优化、解医疗资源分配优化、设施布局优化、可视域基站和无人机选址优化 **2 机器学习和深度学习方面** 卷积神经网络(CNN)、LSTM、支持向量机(SVM)、最小二乘支持向量机(LSSVM)、极限学习机(ELM)、核极限学习机(KELM)、BP、RBF、宽度学习、DBN、RF、RBF、DELM、XGBOOST、TCN实现风电预测、光伏预测、电池寿命预测、辐射源识别、交通流预测、负荷预测、股价预测、PM2.5浓度预测、电池健康状态预测、水体光学参数反演、NLOS信号识别、地铁停车精准预测、变压器故障诊断 **3 图像处理方面** 图像识别、图像分割、图像检测、图像隐藏、图像配准、图像拼接、图像融合、图像增强、图像压缩感知 **4 路径规划方面** 旅行商问题(TSP)、车辆路径问题(VRP、MVRP、CVRP、VRPTW等)、无人机三维路径规划、无人机协同、无人机编队、机器人路径规划、栅格地图路径规划、多式联运运输问题、车辆协同无人机路径规划、天线线性阵列分布优化、车间布局优化 **5 无人机应用方面** 无人机路径规划、无人机控制、无人机编队、无人机协同、无人机任务分配 **6 无线传感器定位及布局方面** 传感器部署优化、通信协议优化、路由优化、目标定位优化、Dv-Hop定位优化、Leach协议优化、WSN覆盖优化、组播优化、RSSI定位优化 **7 信号处理方面** 信号识别、信号加密、信号去噪、信号增强、雷达信号处理、信号水印嵌入提取、肌电信号、脑电信号、信号配时优化 **8 电力系统方面** 微电网优化、无功优化、配电网重构、储能配置 **9 元胞自动机方面** 交通流 人群疏散 病毒扩散 晶体生长 **10 雷达方面** 卡尔曼滤波跟踪、航迹关联、航迹融合

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值