二分查找需满足数据严格有序、支持随机访问、集合相对静态三条件,边界处理须防溢出、统一用left

二分查找不是“用出来就快”的算法,而是靠前提约束和边界控制共同保障 $O(log N)$ 效率的检索模式。它快得稳定,但快得有门槛。
必须满足的三个硬性条件
缺一不可,否则时间复杂度无法保证:
- 数据必须严格有序:升序或降序均可,但需全程一致;若数组部分无序或含重复未排序段,结果不可靠
- 支持随机访问:底层结构需能在 $O(1)$ 时间内定位任意下标元素,如数组、ArrayList;链表不适用
- 集合相对静态:频繁插入/删除会破坏有序性,每次维护排序代价为 $O(N)$,远超查找收益
关键实现细节决定成败
看似简单,90% 的错误出现在边界处理上:
-
防整数溢出的中点计算:用
left + (right - left) / 2替代(left + right) / 2,尤其在大索引(如接近INT_MAX)时避免越界 -
循环终止条件统一用
left:这是最直观、容错性最强的写法;用left 易漏判单元素区间 -
边界收缩严格对称:当
arr[mid] > target时,right = mid - 1;当arr[mid] 时,<code>left = mid + 1;不跳过、不重叠、不越界
从基础查找扩展到高阶用途
二分不只是找“相等”,利用其单调性可解决一类有序场景问题:
-
查找左边界(第一个 ≥ target 的位置):相等时不立即返回,继续向左收缩
right = mid - 1 -
查找右边界(最后一个 ≤ target 的位置):相等时不返回,继续向右收缩
left = mid + 1 - 计算排名(rank):即“有多少元素小于 target”,等价于左边界索引
-
查找前驱/后继:在 rank 基础上取
arr[rank-1]或arr[rank](需越界检查)
何时该用、何时不该用?
判断依据不是“数据大不大”,而是读写比:
- 推荐场景:配置项索引、只读词典、离线日志时间戳定位、编译期常量表、数据库索引底层(B+树的二分思想延伸)
- 应规避场景:实时消息队列、用户动态列表(频繁增删)、内存受限嵌入式设备中无法预分配连续大数组的情况
- 折中方案:若需兼顾查询与更新,考虑平衡树(如 AVL、红黑树)或跳表,它们在 $O(log N)$ 查询基础上支持 $O(log N)$ 插删










