题目
使用分治法在数组中查找目标元素
信息
- 类型:问答
- 难度:⭐
考点
分治算法,二分查找,递归实现
快速回答
使用分治法实现二分查找的核心步骤:
- 确定数组中间位置 mid
- 比较中间元素与目标值:
- 若相等则返回索引
- 若目标值较小,则在左半部分递归查找
- 若目标值较大,则在右半部分递归查找
- 当搜索范围无效时返回 -1
时间复杂度:O(log n),空间复杂度:O(log n)(递归栈)
解析
原理说明
分治算法通过将问题分解为更小的子问题来解决复杂问题。在二分查找中:
1. 分解:将有序数组分为左右两半
2. 解决:判断目标值可能存在的子数组
3. 合并:直接返回子问题的解(无需合并步骤)
代码示例
def binary_search(arr, target, left, right):
if left > right:
return -1 # 基线条件:搜索范围无效
mid = (left + right) // 2
if arr[mid] == target:
return mid # 找到目标
elif arr[mid] > target:
return binary_search(arr, target, left, mid-1) # 左半部分递归
else:
return binary_search(arr, target, mid+1, right) # 右半部分递归
# 使用示例
arr = [2, 5, 8, 12, 16, 23, 38, 56]
target = 23
result = binary_search(arr, target, 0, len(arr)-1)
print(f"元素 {target} 的索引是: {result}") # 输出: 元素 23 的索引是: 5最佳实践
- 输入验证:始终检查数组是否有序
- 边界处理:明确开闭区间(本例使用闭区间 [left, right])
- 溢出预防:计算 mid 时使用
left + (right - left) // 2避免整数溢出 - 尾递归优化:可改写成迭代形式降低空间复杂度至 O(1)
常见错误
| 错误类型 | 示例 | 修正方案 |
|---|---|---|
| 无限递归 | left = mid 代替 left = mid+1 | 确保每次递归缩小搜索范围 |
| 边界错误 | 忽略 left > right 的终止条件 | 优先处理基线条件 |
| 索引计算 | (left+right)//2 未考虑整数溢出 | 使用 left + (right-left)//2 |
扩展知识
- 分治三步曲:分解 → 解决 → 合并(二分查找无需合并)
- 与遍历对比:O(log n) vs O(n) 的时间复杂度优势
- 变体问题:
- 查找第一个/最后一个匹配元素
- 旋转有序数组搜索
- 模糊查找(最接近的值)
- 应用场景:数据库索引、游戏中的快速检索、大规模数据查询