![](https://img-blog.csdnimg.cn/img_convert/3ef767caae7f20900c62e2344633c6f3.png)
![](https://img-blog.csdnimg.cn/img_convert/ce277e71d23d2a2869176355b2e0bcf2.png)
![](https://img-blog.csdnimg.cn/img_convert/5f9d6c9f24a1d1193db39c3a5e8908cb.png)
1、二分查找
- 如果是一个普通升序数组,只需要
mid
值与target
之间的简单判断:
-
- 如果
nums[mid] == target
,则直接返回mid
值 - 如果
nums[mid] < target
,则target
在mid
的后半部分,low = mid+1
- 如果
nums[mid] > target
,则target
在mid
的前半部分,high = mid-1
- 旋转升序数组从任意位置劈开后,至少有一半是有序的,因此可以先找到有序的一段,然后看
target
在不在这一段里,如果在,就把另一半丢弃;如果不在,就把这一段丢弃。
- 先判断
nums[mid]
和nums[high]
的大小,以确定哪一半是升序区间,并判断target
是否在该区间中,从而进一步判断是更新low
还是high
:
-
- 如果
nums[mid] == target
,则直接返回mid
值 - 如果
nums[mid] < nums[high]
,表明后半部分严格升序,此时判断target
是否位于后半部分区间即可更新low
或high
值 - 如果
nums[mid] > nums[high]
,表明前半部分严格升序;此时判断target
是否位于前半部分区间即可更新low
或high
值 - 如果
nums[mid] == nums[high]
(只有当有序pivot
数组中允许数值重复才有可能出现该情况)
class Solution:
def search(self, nums: List[int], target: int) -> int:
low, high = 0, len(nums) - 1
while low <= high:
mid = low + (high - low) // 2
# jy: 如果 mid 值即为目标值, 直接返回
if nums[mid] == target:
return mid
if nums[mid] < nums[high]:
# jy: 当 target == nums[high] 时也更新 low, 使得不会错过正确值
if nums[mid] < target <= nums[high]:
low = mid + 1
else:
high = mid - 1
elif nums[mid] > nums[high]:
if nums[low] <= target < nums[mid]:
high = mid - 1
else:
low = mid + 1
# jy: 只有当有序 pivot 数组中允许数值重复才有可能出
# 现 nums[mid] == nums[high] 的情况 (如 0081)
else:
#high -= 1
high = mid - 1
return -1
nums = [4, 5, 6, 7, 0, 1, 2]
target = 0
res = Solution().search(nums, target)
print(nums, " === ", target, " === ", res)
target = 3
res = Solution().search(nums, target)
print(nums, " === ", target, " === ", res)
nums = [3, 4, 5, 6, 7, 0, 1, 2]
target = 4
res = Solution().search(nums, target)
print(nums, " === ", target, " === ", res)
2、改写解法 1
class Solution:
def search(self, nums: List[int], target: int) -> int:
pass