0081. 搜索旋转排序数组 II
大约 3 分钟
0081. 搜索旋转排序数组 II
- 标签:数组、二分查找
- 难度:中等
题目链接
题目大意
描述:一个按照升序排列的整数数组 ,在位置的某个下标 处进行了旋转操作。(例如: 可能变为 )。
现在给定旋转后的数组 和一个整数 。
要求:编写一个函数来判断给定的 是否存在与数组中。如果存在则返回 True
,否则返回 False
。
说明:
- 。
- 。
- 题目数据保证 在预先未知的某个下标上进行了旋转。
- 。
示例:
- 示例 1:
输入:nums = [2,5,6,0,0,1,2], target = 0
输出:true
- 示例 2:
输入:nums = [2,5,6,0,0,1,2], target = 3
输出:false
解题思路
思路 1:二分查找
这道题算是「0033. 搜索旋转排序数组」的变形,只不过输出变为了判断。
原本为升序排列的数组 nums 经过「旋转」之后,会有两种情况,第一种就是原先的升序序列,另一种是两段升序的序列。
*
*
*
*
*
*
*
*
*
*
*
*
最直接的办法就是遍历一遍,找到目标值 target。但是还可以有更好的方法。考虑用二分查找来降低算法的时间复杂度。
我们将旋转后的数组看成左右两个升序部分:左半部分和右半部分。
有人会说第一种情况不是只有一个部分吗?其实我们可以把第一种情况中的整个数组看做是左半部分,然后右半部分为空数组。
然后创建两个指针 、,分别指向数组首尾。让后计算出两个指针中间值 。将 与两个指针做比较,并考虑与 的关系。
如果 ,则 在左半部分(因为右半部分值都比 小)。
- 如果 ,并且 ,则 在左半部分,并且在 左侧,此时应将 左移到 位置。
- 否则如果 ,则 在左半部分,并且在 右侧,此时应将 右移到 。
- 否则如果 ,则 在右半部分,应将 移动到 位置。
如果 ,则 在右半部分(因为右半部分值都比 小)。
- 如果 ,并且 ,则 在右半部分,并且在 右侧,此时应将 右移到 位置。
- 否则如果 ,则 在右半部分,并且在 左侧,此时应将 左移到 位置。
- 否则如果 ,则 在左半部分,应将 左移到 位置。
最终判断 是否等于 ,如果等于,则返回
True
,否则返回False
。
思路 1:代码
class Solution:
def search(self, nums: List[int], target: int) -> bool:
n = len(nums)
if n == 0:
return False
left = 0
right = len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[left]:
if nums[left] <= target and target <= nums[mid]:
right = mid
else:
left = mid + 1
elif nums[mid] < nums[left]:
if nums[mid] < target and target <= nums[right]:
left = mid + 1
else:
right = mid
else:
if nums[mid] == target:
return True
else:
left = left + 1
return nums[left] == target
思路 1:复杂度分析
- 时间复杂度:,其中 是数组 的长度。最坏情况下数组元素均相等且不为 ,我们需要访问所有位置才能得出结果。
- 空间复杂度:。