33. 搜索旋转排序数组
思路
-
二分法
先对着代码进行讲解。
class Solution:
def search(self, nums: List[int], target: int) -> int:
# low和high分别指向数组2端
low, high = 0, len(nums)-1
while low <= high:
mid = (low+high) // 2
# 如果nums[mid]与目标相等,直接return,这里没有异议
if nums[mid] == target:
return mid
elif nums[mid] > target:
# 这里开始出现分歧,虽然中位数大于了目标,由于存在
# 旋转的可能,如果低位也大于目标且低位到中位是递增的
# 那么可以肯定左半段没有等于target的数了,所以往右侧找
if nums[low] > target and nums[low] <= nums[mid]:
low = mid+1
# 否则与正常二分保持一致
else:
high = mid-1
else:
# 同上
if nums[high] < target and nums[high] >= nums[mid]:
high = mid - 1
else:
low = mid + 1
return -1
虽然这个数组是被旋转了,但是也满足二分搜索条件,只不过需要做一定的转换。
我们来看下面这个例子: [5, 1, 3] 当目标元素是5的时候,首先二分会找到1,按照以往的数组,这时候low应该等于mid+1,但在这里不一样,因为数组有可能已经被旋转了。
所以需要往左侧走,high = mid-1,当然这个也是有条件的,那就是此时nums[high]也比target小,并且nums[high]要保证大于nums[mid],也就是说后半段要是递增的,那就肯定没有数字比target大了,这时候才会去左边查找。
同理当target比nums[mid]小的时候也是一样。
里面还是有许多坑的,比如递增的条件一定要≥,否则有部分用例会发现你的bug。
大家写完之后可以多写点特殊场景的用例自测一下再提交,通过的概率会大很多!