🤔 为什么要用二分?
因为快!一个数一个数地找(顺序查找)要 O(n),二分查找只要 O(logn)。数据越大,二分越划算——10 亿个数据,顺序找最多要 10 亿次,二分最多 30 次!
复杂度对比 拖动滑块,感受差距
2^10 = 1,024
二分比顺序快 约 100 倍!
二分查找 vs 二分答案
🔍 二分查找
找值:t 在不在数组里?在哪个位置?
比较:a[mid] 和 t 比大小
例:在 [1,3,5,7,9] 里找 7
🆚
🎯 二分答案
找解:哪个答案能满足条件?
判断:check(mid) 行不行
例:答案在区间里,试哪个解满足
口诀:找值用比较,找解用 check!
🔍 二分查找:在有序数组里找 t
每次拿 mid = (l+r)/2 位置的数和 t 比较:相等就找到;a[mid] < t 就去右半(l = mid+1);否则去左半(r = mid-1)。每轮范围砍掉一半,O(logn) 搞定!
数组 橙色 = 正在比较,绿色 = 找到,灰 = 已排除
搜索范围
mid 中间值
找到 t
已排除
控制台
速度
binary_search.cppC++
📐 二分答案:找第一个"大于 t"的数
check(x) 问:x 是不是 不够大(x ≤ t)?不够大就 l = mid+1 往右找;够大了就 r = mid-1 往左收。循环结束,l 指向第一个大于 t 的数。
数组 红色 = 大于 t 的候选答案,灰色 = 不够大
搜索范围
正在检查
大于 t
最终答案
控制台
速度
lower_bound.cppC++
📐 二分答案:找最后一个"小于 t"的数
check(x) 问:x 是不是 小于 t?是就说明答案还能更大,l = mid+1;不是就 r = mid-1 往左收。循环结束,r 指向最后一个小于 t 的数。
数组 绿色 = 小于 t 的候选,灰色 = 不小于 t
搜索范围
正在检查
小于 t
最终答案
控制台
速度
upper_bound.cppC++