LeetCode搜索旋转排序数组 二分查找
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
进阶:你可以设计一个时间复杂度为 O(log n) 的解决方案吗?
思路:
看到题目搜索+升序排列+进阶要求logN,就是二分查找没跑啦。只不过这个题整了一点花样,不是完全升序,而是中间有个交换。所以二分查找策略的也要相应的调整,这也是这个题的难点。
如果不管进阶要求,遍历地去做,多半是要被挂的(被挂代码,请勿使用):
class Solution(object):
def search(self, nums, target):
for i in range(len(nums)):
if nums[i]==target:
return i
return -1
二分查找的思路如下:
比如现在有个数组:4 5 6 7 / 0 1 2 3,中间的/表示旋转边界,照常规二分查找思路,定义一个left在左边,right在右边,我们得到 mid = left+(right-left)//2,假如nums[mid]==target,那正好找到了,皆大欢喜,结束;否则,我们需要先判断,这个mid的位置是在旋转边界的“左边”还是“右边”。判断方式很简单,拿nums[mid]与nums[left]比较,在这个例子中,第一轮的nums[left]是4,如果nums[mid]大于4,则在旋转边界左边,反之在右边。
我们只有先确定了mid在哪里,才能正确地判断target在mid的哪一边。
假如mid在旋转边界的左边,则target若处于nums[left]和nums[mid]之间,target就在mid左边,否则在mid右边;
假如mid在旋转边界右边,则target若处于nums[target]和nums[right]之间,target就在mid右边,否则在mid左边。
这些只是看起来有点绕,但无非就是先确定mid的位置在旋转边界的左还是右,然后对于不同情况去判断target在mid的左还是右即可。因为二分查找的本质就是一遍遍地通过探索target在mid的相对方向来逼近结果的,对吧?
代码:
class Solution(object):
def search(self, nums, target):
lenth = len(nums)
left = 0
right = lenth-1
while(right>=left): #二分查找 我习惯写上等于号
mid = left+(right-left)//2
if target==nums[mid]:
return mid
if nums[mid]<nums[left]:#mid在右段
#左边界和右边界就写left和right 不是0和-1
if target>nums[mid] and target<=nums[right]:#如果target在mid的右边
#最关键就是上面这个条件是个范围
left=mid+1
else:#太大了以至于来到了左边或者更小时,就在左边
right=mid-1
else:#mid在左段
if target>=nums[left] and target<nums[mid]:#若target在mid左边
right=mid-1
else:#target在mid右边
left=mid+1
return -1
小结:
代码里写的mid = left+(right-left)//2,和(left+right)//2其实没太大区别,只不过前者可以避免left和right都很大时两数相加太大超内存。不过应该也不至于,反正差不多,可以作为一个写二分查找时无关紧要的习惯,不用太纠结。
对于二分查找搜索的变式一共也就没几道题,一半理解一半记忆就可以搞定了,这道搜索旋转排序数组还是比较经典的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了