std::binary_search 返回布尔值表示是否找到,参数为起始迭代器、结束迭代器、待查值,要求范围严格升序排列且左闭右开。

binary_search 函数怎么用,参数顺序和前提条件是什么
std::binary_search 是 C++ 标准库提供的二分查找工具,但它**不返回位置,只返回是否找到**。它要求容器(或迭代器范围)已严格升序排列——不是“大致有序”,也不是降序,否则行为未定义。
常见误用:binary_search(v.begin(), v.end(), x) 在 v 未排序时返回随机结果;或者对 vector 调用前忘了 sort。
- 必须传入两个迭代器:起始和结束(左闭右开),比如
v.begin()和v.end() - 第三个参数是待查值,类型需与元素可比较(通常支持
) - 可选第四个参数为自定义比较函数,例如
binary_search(a, b, x, greater用于降序数组(但此时你得自己保证降序)()) - 头文件是
,不是或(后者不存在)
手写二分查找时,l、r 初始值和循环条件怎么设才不出界
最容易出错的是边界处理:l = 0, r = n 还是 r = n - 1?while (l 还是 while (l ?这取决于你想要的语义和返回值类型。
推荐统一用「左闭右开」区间风格,即 l = 0, r = n,配合 while (l :
立即学习“C++免费学习笔记(深入)”;
int lower_bound(const vector& a, int x) { int l = 0, r = a.size(); while (l < r) { int m = l + (r - l) / 2; if (a[m] < x) l = m + 1; else r = m; } return l; // 第一个 >= x 的位置,可能等于 a.size() }
- 不用
(l + r) / 2防止整数溢出,一律用l + (r - l) / 2 - 更新
r = m(不是m - 1),因为m本身可能是答案(如找下界) - 循环结束时
l == r,且该位置具有明确含义(如lower_bound或upper_bound) - 若要返回是否存在,只需判断
l
binary_search 和手写版性能差多少,什么时候必须手写
性能上几乎没有差别——binary_search 内部就是标准二分逻辑,编译器优化后和手写几乎一致。但关键区别不在速度,而在**控制粒度**。
- 你需要下标位置(比如修改后续元素)?
binary_search不行,得用lower_bound或手写 - 你要找第一个满足条件的索引(不一定是相等),比如 “第一个大于 x 的数”?必须手写或组合
lower_bound - 你在写模板库或嵌入式环境,不想依赖
?那只能手写 - 数组是降序的,又不想反转?
binary_search配greater可以,但手写改一个比较符号更直观()
顺带一提:lower_bound / upper_bound 也属于 ,它们返回迭代器,比 binary_search 更常用,也更值得优先掌握。
调试二分时最常见的三个错误现象及快速定位法
二分写挂了,八成不是算法错,而是某处小细节失控。下面三个现象一出现,基本能秒定位:
- 死循环:检查
l和r是否在某次迭代中完全没变——大概率是m计算后,分支更新漏了+1或-1,比如该写l = m + 1却写了l = m - 返回 -1 却实际存在:检查是否把
a[m] == x放进了else分支却没单独处理,导致相等时被归入“太大”分支(典型错误是if (a[m] > x) r = m - 1; else l = m + 1;,漏了相等情况) - 越界访问:打印
m值,看是否曾等于n或负数——说明初始r设成了n却用了循环,或r设成了n - 1却在更新时用了r = m(而非m - 1)
真遇到问题,先加一行 cout ,跑两轮就清楚卡在哪了。别猜,直接看中间状态。










