33. 搜索旋转排序数组
整数数组
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。
题目链接:33. 搜索旋转排序数组 - 力扣(LeetCode) (leetcode-cn.com)
二分搜索
思路:
根据之前写的 leetcode153 的思路,可以先找数组的最小值,也就是将数组分为两个升序数组,判断target在哪个数组,然后再次使用二分法,查找是否有目标数。
- 首先判断特殊情况,数列中只有一个数字,可以直接判断该数字是否为目标值,若是目标值则返回0,否则返回-1
- 接着判断是否需要划分为两个数组
- 若数组的首小于数组的尾则说明这个数组依旧是一个递增数组,不必划分。
- 否则需要划分数组,找到目标值可能存在的区间
- 划分数组也是使用二分法
- 首先初始化设置左右两个指针
left = 0和right = len(nums)-1 - 我们希望最后
left是指向第一个递增数组的尾部,即left为原数组的最大值,right是指向第二个递增数组的首部,right为原数组的最小值。 - 退出循环时
left = right - 1,所以while循环的条件可以设置为left < right-1 - 若目标值小于最小值
target < nums[right],或者说大于最大值target > nums[left],那么直接返回-1 - 若目标值大于等于
nums[0],则表示目标值在左边的递增数组中。否则就在右边的递增数组中。
- 首先初始化设置左右两个指针
- 接着还是一个二分法来在递增数组中寻找目标值
- 依旧设置左右两个指针
left和right - 循环条件
left <= right mid的设置,防止溢出mid = left + (right-left)//2- 当
mid指向的值正好等于目标值时,直接返回mid - 若小于则说明目标值在右边,
left = mid + 1 - 若大于则说明目标值在左边,
right = mid - 1
- 依旧设置左右两个指针
class Solution:
def search(self, nums: List[int], target: int) -> int:
n = len(nums)
if n == 1:
if nums[0] == target:
return 0
else:
return -1
if nums[0] > nums[n-1]:
left = 0
right = n-1
while(left < right-1):
mid = left + (right-left)//2
if nums[mid] < nums[right]:
right = mid
elif nums[mid] > nums[right]:
left = mid
if target < nums[right] or target > nums[left]:
return -1
if target >= nums[0]:
right = left
left = 0
elif target < nums[0]:
left = right
right = n-1
elif nums[0] < nums[n-1]:
if target < nums[0] or target > nums[n-1]:
return -1
left = 0
right = n-1
while (left <= right):
mid = left + (right-left)//2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
return -1
浙公网安备 33010602011771号