二分查找常见操作总结
1. 基本二分查找
目标: 在有序数组 nums
中查找 target
的索引(如果存在)。
适用场景:
- 需要在 有序数组 中查找某个特定元素。
- 适用于无重复元素的情况。
示例:
输入 nums = [1, 2, 3, 4, 5], target = 3
,输出 2
。
def binary_search(nums, target):left, right = 0, len(nums) - 1while left <= right:mid = (left + right) // 2if nums[mid] == target:return midelif nums[mid] < target:left = mid + 1else:right = mid - 1return -1 # 没找到
2. 查找左边界(Lower Bound)
目标: 找到 第一个 大于等于 target
的元素索引。
适用场景:
- 用于查找 某个值的最左侧出现位置,如查找元素插入的位置。
- 有重复元素 时,找到
target
最左边的位置。
示例:
输入 nums = [1, 2, 2, 2, 3], target = 2
,输出 1
。
def lower_bound(nums, target):left, right = 0, len(nums) - 1while left <= right:mid = (left + right) // 2if nums[mid] < target:left = mid + 1else:right = mid - 1return left # 返回的是第一个大于等于 target 的索引
3. 查找右边界(Upper Bound)
目标: 找到 第一个 大于 target
的元素索引。
适用场景:
- 需要获取比目标值大的第一个位置。
- 可用于计算某个值的出现次数。
示例:
输入 nums = [1, 2, 2, 2, 3], target = 2
,输出 4
。
def upper_bound(nums, target):left, right = 0, len(nums) - 1while left <= right:mid = (left + right) // 2if nums[mid] <= target:left = mid + 1else:right = mid - 1return left # 返回的是第一个大于 target 的索引
4 查找插入位置
目标: 找到 target
应该插入 的位置。
适用场景:
- 需要在 有序数组 中插入一个新元素,并保持有序性。
- 可用于 二分搜索的变体,比如寻找目标元素的最左/最右位置。
示例:
输入 nums = [1, 3, 5, 6], target = 5
,输出 2
。
def search_insert_position(nums, target):left, right = 0, len(nums) - 1while left <= right:mid = (left + right) // 2if nums[mid] == target:return midelif nums[mid] < target:left = mid + 1else:right = mid - 1return left # 返回插入位置
5. 寻找旋转排序数组中的最小值
目标: 在 旋转排序数组 中找到 target
。
适用场景:
- 需要在 部分有序数组(如旋转排序数组)中进行二分查找。
nums
在某个位置发生了 旋转,但仍然部分有序。
示例:
输入 nums = [4, 5, 6, 7, 0, 1, 2], target = 0
,输出 4
。
def findMin(nums: List[int]) -> int:left, right = 0, len(nums) - 1 # 闭区间 [0, n-1]while left < right: # 只要区间不缩至一个元素mid = (left + right) // 2if nums[mid] > nums[right]: # mid 在左半部分left = mid + 1 # 缩小左边界else: # mid 在右半部分right = mid # 缩小右边界,保持 `right` 包含在内return nums[left] # 最终 `left == right`,即最小值下标
二分查找常见操作对比表
操作 | 目标 | 适用场景 | 返回值 | 示例输入 | 示例输出 |
---|---|---|---|---|---|
基本二分查找 | 在有序数组中查找目标值的索引 | 数组 无重复元素,查找某个特定元素 | 目标值的索引,若不存在返回 -1 | nums = [1,2,3,4,5], target = 3 | 2 |
查找左边界 (Lower Bound) | 找到第一个大于等于 target 的元素索引 | 有重复元素,查找 target 最左侧的位置 | target 在数组中的最左索引,若不存在返回插入位置 | nums = [1,2,2,2,3], target = 2 | 1 |
查找右边界 (Upper Bound) | 找到第一个大于 target 的元素索引 | 有重复元素,查找 target 右侧界限 | 返回大于 target 的第一个索引 | nums = [1,2,2,2,3], target = 2 | 4 |
查找插入位置 | 找到 target 应插入的位置 | 在有序数组中插入新元素,并保持有序性 | target 应插入的位置 | nums = [1,3,5,6], target = 5 | 2 |
寻找旋转排序数组中的最小值 | 在旋转排序数组中找到最小值 | 旋转排序数组 | 数组中的最小值 | nums = [4,5,6,7,0,1,2] | 0 |