一、二分查找
- 如果查找不到,返回的是该插入位置
- 如果有多个值和target一样,返回的是第一个
python
def binary_search(nums, target):
left, right = -1, len(nums)
while left+1<right:
# 循环不变量
# nums[left] < target
# nums[right] >= target
mid = (left+right)//2
if nums[mid] < target: # 和循环不变量对齐
left = mid
else:
right = mid
return right
二、红蓝染色法
- 基本概念
红蓝染色法是一种借助二分查找高效解决:需要找到满足特定条件的所有元素中的第一个或最后一个位置的情况
红色区域:小于当前值的
蓝色区域:大于等于当前值的
应用场景:
- 找到 ≥ x ≥x ≥x的第一个元素
- 找到 > x >x >x的第一个元素
- 找到 ≤ x ≤x ≤x的最后一个元素
- 找到 < x <x <x的最后一个元素
换句话说:二分查找的目标是找到红蓝边界,即第一个满足条件的元素。
三、162. 寻找峰值

- 思路:红蓝染色法
每次用nums[mid] 和 nums[mid+1] 比较,如果nums[mid] > nums[mid+1],那么右边全是红色(小于target),否则,左边全是红色 - 代码:
python
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
''''
因为最右边元素一定要么是峰顶,要么是峰顶左边元素,所以不用检测(否则下面的代码报错,当峰顶就是最右的时候)
为什么要检测-1,因为返回的right,本身right就是指向>=target的。
'''
left, right = -1, len(nums)-1
while left+1<right:
mid = (left+right)//2
if nums[mid] > nums[mid+1]:
right = mid
else:
left=mid
return right
三、153. 寻找旋转排序数组中的最小值

- 思路:
假设数组最后一个元素是最小值或者最小值的左值,那么直接做二分查找,把最后一个元素当作最小值就行。
假设数组最后一个元素不是最小值或者其左值,那么根据红蓝染色法,二分查找可以找到第一个满足条件的元素。 - 代码:
python
class Solution:
def findMin(self, nums: List[int]) -> int:
left, right = -1, len(nums)-1
while left+1<right:
mid = (left+right)//2
if nums[mid] < nums[-1]:
right = mid
else:
left = mid
return nums[right]
一、33. 搜索旋转排序数组

- 思路: