元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
算法基础
▶
复杂度分析
时间复杂度
空间复杂度
渐进符号
▶
算法思想
分治法
贪心算法
回溯法
概率算法
枚举算法
递推算法
递归算法
动态规划
分支限界法
模拟算法
▶
算法分析
正确性证明
性能优化
算法比较
▶
搜索算法
▶
基本搜索
顺序搜索
二分搜索
插值搜索
▶
图搜索
深度优先搜索
广度优先搜索
启发式搜索
▶
高级搜索
双向搜索
A*算法
模式匹配
▶
排序算法
▶
比较类排序
冒泡排序
快速排序
归并排序
插入排序
选择排序
▶
非比较类排序
计数排序
基数排序
桶排序
▶
高级排序
堆排序
希尔排序
外部排序
拓扑排序
▶
图论算法
▶
图的表示
邻接矩阵
邻接表
边集数组
▶
最短路径
Dijkstra算法
Floyd算法
Bellman-Ford算法
最短路径概述
▶
生成树
Prim算法
Kruskal算法
并查集
最小生成树
▶
图的连通性
强连通分量
割点与桥
双连通分量
欧拉路径
▶
动态规划
▶
基础概念
最优子结构
重叠子问题
状态转移方程
▶
经典问题
背包问题
最长公共子序列
编辑距离
▶
优化技巧
空间优化
状态压缩
区间动态规划
▶
字符串算法
▶
字符串匹配
KMP算法
Boyer-Moore算法
Sunday算法
▶
字符串处理
字典树
后缀数组
字符串哈希
▶
压缩算法
游程编码
Huffman编码
LZ77算法
发布时间:
2025-03-21 18:24
↑
☰
# 二分搜索 二分搜索(Binary Search)是一种高效的搜索算法,它通过将有序数组分成两半并比较中间元素来定位目标值。这种方法每次都能将搜索范围减半,因此效率远高于顺序搜索。 ## 基本原理 二分搜索的工作原理如下: 1. 确保数组已经排序 2. 找到数组的中间位置 3. 将中间元素与目标值比较 4. 如果相等,则找到目标值 5. 如果目标值小于中间元素,在左半部分继续搜索 6. 如果目标值大于中间元素,在右半部分继续搜索 7. 重复步骤2-6,直到找到目标值或确定目标值不存在 ## 代码实现 ### 基本实现 ```python def binary_search(arr, target): left = 0 right = len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid # 找到目标值,返回索引 elif arr[mid] < target: left = mid + 1 # 目标值在右半部分 else: right = mid - 1 # 目标值在左半部分 return -1 # 未找到目标值 # 使用示例 arr = [1, 3, 5, 7, 9, 11, 13, 15] target = 7 result = binary_search(arr, target) print(f"元素 {target} 的位置是: {result}") ``` ### 递归实现 ```python def binary_search_recursive(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_recursive(arr, target, mid + 1, right) else: return binary_search_recursive(arr, target, left, mid - 1) # 使用示例 arr = [1, 3, 5, 7, 9, 11, 13, 15] target = 7 result = binary_search_recursive(arr, target, 0, len(arr) - 1) print(f"元素 {target} 的位置是: {result}") ``` ## 性能分析 ### 时间复杂度 - 最好情况:O(1) - 目标值在中间位置 - 最坏情况:O(log n) - 需要多次折半 - 平均情况:O(log n) - 每次将搜索范围减半 ### 空间复杂度 - 迭代实现:O(1) - 只需要常量额外空间 - 递归实现:O(log n) - 递归调用栈的深度 ### 优缺点分析 优点: 1. 搜索效率高,时间复杂度为O(log n) 2. 实现相对简单 3. 内存占用小(迭代版本) 缺点: 1. 要求数组必须有序 2. 不适用于频繁插入删除的场景 3. 只能应用于数组等支持随机访问的数据结构 ## 应用场景 1. 在有序数组中查找元素 2. 查找插入位置以维护有序性 3. 优化其他算法的搜索过程 4. 解决一些特定的算法问题 ## 实际应用示例 ### 1. 查找插入位置 ```python def search_insert_position(arr, target): left = 0 right = len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return left # 返回应该插入的位置 # 使用示例 arr = [1, 3, 5, 6] target = 4 position = search_insert_position(arr, target) print(f"元素 {target} 应该插入到位置: {position}") ``` ### 2. 查找范围 ```python def search_range(arr, target): def find_first(): left = 0 right = len(arr) - 1 result = -1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: result = mid right = mid - 1 # 继续向左搜索 elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return result def find_last(): left = 0 right = len(arr) - 1 result = -1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: result = mid left = mid + 1 # 继续向右搜索 elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return result return [find_first(), find_last()] # 使用示例 arr = [5, 7, 7, 8, 8, 8, 10] target = 8 range_result = search_range(arr, target) print(f"元素 {target} 的范围是: {range_result}") ``` ## 优化技巧 1. 防止整数溢出 ```python mid = left + (right - left) // 2 # 比 (left + right) // 2 更安全 ``` 2. 二分查找的变体 - 查找第一个等于目标值的元素 - 查找最后一个等于目标值的元素 - 查找第一个大于等于目标值的元素 - 查找最后一个小于等于目标值的元素 3. 处理重复元素 - 根据具体需求选择合适的变体 - 可能需要额外的遍历来确定边界 ## 常见问题和解决方案 1. 数组未排序 - 解决方案:先对数组进行排序 - 注意:如果需要记录原始位置,可以存储索引 2. 处理边界情况 - 空数组 - 只有一个元素 - 目标值不在数组范围内 3. 死循环问题 - 确保循环条件正确(left <= right) - 确保每次迭代都能缩小搜索范围 ## 总结 二分搜索是一种高效的搜索算法,它通过不断将搜索范围减半来快速定位目标值。虽然它要求数据必须有序,但在处理大规模有序数据时,其O(log n)的时间复杂度使它成为最佳选择之一。掌握二分搜索的各种变体和优化技巧,可以帮助我们更好地解决实际问题。在实践中,要注意处理好边界情况和重复元素的情况,确保算法的正确性和稳定性。