sort.search是go标准库最稳妥的二分查找入口,但查相等值需两步:先用a[i] >= target找左边界,再验证idx
sort.Search是标准库提供的二分入口,但直接用它查“相等”会出错——它不找值,只找第一个满足条件的位置。你得自己把语义转成a[i] >= target,再手动验证。用
sort.Search查相等值必须两步走很多人写成
sort.Search(len(a), func(i int) bool { return a[i] == target }),这会导致:找不到时返回插入点(比如[]int{1,3,5}查 4,返回索引 2),但a[2]是 5,≠4;更糟的是,当i == len(a)时闭包里访问a[i]会 panic。
- 正确断言只能是
a[i] >= target(升序前提下)- 调完必须显式检查:
if idx- 空切片、全小于、全大于 target 都会返回合法索引(0 或
len(a)),不判就崩- 想省事用
sort.SearchInts(a, target)?它只是sort.Search的薄封装,底层完全一样
binarySearch迭代版怎么写才不容易错手写推荐闭区间
[left, right],循环条件是left ,退出时 <code>left > right就代表真没找到。
- 中点必须写成
left + (right - left) / 2,不是(left + right) / 2——后者在极端偏移或大内存映射场景可能整数溢出- 比较后移动规则简单统一:
a[mid] > target → right = mid - 1;a[mid]- 命中即返,不用额外状态变量;返回前别忘检查越界(虽然循环已控,但逻辑清晰更重要)
找重复元素的左右边界怎么改
基础版一找到就返回,但业务常要“第一个 3”或“最后一个 3”。本质还是二分,只是命中时不急着停,而是继续缩区间。
- 找左边界:命中时执行
right = mid - 1,最后检查left是否越界及a[left] == target- 找右边界:命中时执行
left = mid + 1,最后检查right是否越界及a[right] == target- 降序数组不能直接套:要么翻转断言为
a[i] ,要么先转升序——<code>sort.Search不支持降序语义递归版能不能用,哪些坑最致命
递归语义清楚,但生产环境不推荐。Go 默认栈深度有限,且每次调用有开销;更隐蔽的问题是:容易忽略返回值传递。
- 常见错误:递归调用写了
BinarySearch(...)却没接返回值,结果永远返回零值- 参数必须带
low、high,别传子切片(会复制底层数组,O(n) 开销)- 终止条件是
low > high,不是len(arr) == 0(后者低效且易错)- 哪怕数据量百万级(log₂(1e6) ≈ 20 层),递归也无性能优势,纯属增加 panic 风险
所有二分都依赖升序前提,这点一旦漏验,后续全是幻觉。不是“差不多有序”就行,是必须严格单调升序——连等于号都不能乱加。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!












