sort.search用于查找第一个满足条件的位置,需传入返回bool的函数且逻辑为a[i]>=target;降序数组需反转逻辑或转升序;找边界需调整收缩策略并验证越界;所有二分均要求输入升序已排序。

直接用 sort.Search 最省事,但别忘了验证
Go 标准库早给你写好了健壮的二分查找,不用手撸循环——关键是 sort.Search 不是“找相等”,而是“找第一个满足条件的位置”。你传进去的函数必须返回 bool,且逻辑得是 a[i] >= target 这类左边界语义。
- 错误写法:
sort.Search(len(a), func(i int) bool { return a[i] == target })→ 它可能在没找到时返回插入点(比如数组[1,3,5]查4,返回索引2,但a[2]是5,≠4) - 正确流程:先调
idx := sort.Search(len(a), func(i int) bool { return a[i] >= target }),再判断idx - 空切片安全:
sort.Search(0, ...)没问题,返回0,后续idx 自动为 <code>false,不会 panic
binarySearch 手写迭代版:闭区间 [left, right] 最不容易错
自己写的时候,坚持用闭区间(left 为循环条件),能极大减少边界计算出错概率。中点用 <code>left + (right-left)/2 防溢出,不是 (left+right)/2 —— 虽然对 int 很少溢出,但这是工程习惯。
- 移动规则简单:匹配就返;
a[mid] > target→right = mid - 1;a[mid] → <code>left = mid + 1 - 退出时
left > right,说明真找不到,直接返-1 - 降序数组不能直接套用:要么反转逻辑(改比较方向),要么先转升序——
sort.Search也不支持降序,得自己翻转断言
要找重复元素的边界?改写收缩逻辑就行
基础版一找到就返回,但实际业务常要“第一个 3”或“最后一个 3”——本质还是二分,只是命中 == target 时不急着返回,而是继续往左/右缩区间。
- 找左边界:命中时执行
right = mid - 1,最后检查left是否越界及是否真等于target - 找右边界:命中时执行
left = mid + 1,最后检查right - 别漏验证:比如数组
[2,2]查3,左边界搜索后left可能为2(越界),不判就 panic
递归版能写,但没必要在生产环境用
递归写法语义清晰,适合理解原理,但 Go 默认栈深度有限,且每次调用有函数开销。对百万级数组,迭代版稳定,递归版可能栈溢出或慢几个纳秒。
- 参数必须带当前
left、right,不能只传子切片(会复制底层数组,O(n) 开销) - 终止条件是
left > right,不是len(arr) == 0(后者低效且易错) - 如果非要递归,确保尾递归优化不可用的前提下,深度别超几千层——而二分 log₂(1e6) ≈ 20,理论上安全,但无收益
最常被忽略的一点:所有二分查找都要求输入切片**升序且已排序**。没人帮你检查——传个乱序数组,结果一定错,而且错得毫无提示。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











