Lee's Blog
  • 首页
  • 博客
  • 作品
  • 成长
  • 学习
  • 打榜
  • 练习
  • 关于
登录 / 注册
✦

保持联系

关注我的最新动态

GitHubbilibili

© 2026 Lee's Blog

首页/博客/算法学习/算法踩坑-二分法
算法踩坑-二分法
算法学习2026年7月18日6 分钟阅读

算法踩坑-二分法

算法学习
X微博

二分查找踩坑全记录:从基础模板到边界查找,我踩过的所有雷 | 刷题踩坑连载 01

本系列持续更新算法刷题过程中亲手踩过的真实坑点,不照搬标准答案,只记录翻车现场、错误根源和修正思路,既是自己的知识沉淀,也帮你避开同类低级失误。

本文是二分查找模块的完整踩坑汇总,覆盖从基础目标值查找,到左右边界变体的全场景错误。从核心逻辑到语法细节,从普通用例到极端边界,所有踩过的雷都整理在此,做完二分所有题目后对照自查,能规避绝大多数不必要的报错。


一、基础二分通用坑:所有题型都要先避开的雷

这部分是二分查找的底层共性错误,无论是基础题还是边界变体题都会踩,属于写完代码第一优先级自查的内容。

1. 核心逻辑类(全语言通用)

这类错误不区分编程语言,是对二分区间逻辑理解不到位导致的,直接决定代码能不能跑通。

  1. 无边界意识,搜索区间不收敛 不定义 left/right 双指针,直接用数组长度和 mid 推导新 mid,区间永远不会缩小,最终必然死循环超时。本质是没理解二分的核心:用左右指针不断收缩搜索范围,每次砍掉一半区间。

  2. 边界移动方向完全颠倒

  • 当 nums[mid] < target(目标值在 mid 右侧):错误移动右边界 right,正确应收缩左边界 left = mid + 1
  • 当 nums[mid] > target(目标值在 mid 左侧):错误移动左边界 left,正确应收缩右边界 right = mid - 1
  1. 边界不越过 mid,区间收不干净 写成 left = mid / right = mid,区间永远残留 mid 这个元素,当剩下两个元素时会陷入死循环。左闭右闭模板下,mid 已经被比较过了,收缩边界时必须跳过它,用 mid ± 1。

  2. 循环条件用错,空转或越界 用 nums[mid] != target 作为循环条件,一旦目标不存在,循环会无限空转甚至索引越界。正确循环条件是 left <= right,对应左闭右闭区间的终止规则:当右指针跑到左指针左边,说明区间已空,搜索结束。

  3. 漏掉命中分支,找到也不返回 循环内只处理大于、小于两种情况,不写 == target 的返回逻辑,就算找到目标也不会退出,全程空转超时。

  4. 重复计算 mid,平白引入错误 循环开头已经计算过 mid,分支里又手动重复计算,还乱加偏移量,属于多余操作带来的无意义错误。

  5. 区间定义前后不统一 收缩边界用 mid ± 1(对应左闭右闭区间),但初始右边界却写成 nums.length(对应左闭右开区间),从根上逻辑矛盾,边界必然出错。

2. Java 语法专属类

这类是 Java 语言特性导致的低级错误,编译阶段就会暴露,但初学者很容易反复踩。

  1. 数组长度写法颠倒 误写为 length.nums,正确写法是 nums.length。

  2. 分支内重复声明变量 在 if 块里写 int left = ... / int right = ...,相当于新建了同名局部变量,外层的左右指针根本没被修改,循环永远不会结束。修正:直接赋值 left = mid + 1,不要加变量类型声明。

  3. 误用三元返回语法 Java 没有 return A if B else C 的写法;且基础二分场景完全不需要,循环结束直接 return -1 即可。

  4. 变量作用域混淆 mid 在 while 循环内部定义,循环结束后作用域失效,循环外访问 nums[mid] 会直接编译报错。


二、进阶踩坑:左右边界查找专属(LeetCode 34 实战复盘)

掌握基础二分后,做「查找元素首尾位置」这类边界题时,很容易以为只是改改分支逻辑,实则在偏移量、健壮性上踩新的坑。以下是 LeetCode 34「在排序数组中查找元素的第一个和最后一个位置」的专属翻车点。

1. 语法细节翻车:复制代码带来的低级失误

  1. 变量名笔误 复制第一段二分逻辑改右边界代码时,变量名没改干净,出现未定义的 target_ 这类变量,直接编译失败。建议:复用逻辑尽量封装成方法,少用整段复制的方式写代码,减少手滑概率。

  2. 数组初始化与比较语法混淆 用 [a, b] 格式直接创建数组、用 == 比较两个数组的内容,都是混淆了其他语言的语法。 Java 中:

  • 新建数组必须用 new int[]{元素1, 元素2} 的格式
  • == 对比的是数组内存地址,不是元素内容,永远不会返回 true 修正:直接通过边界值构造返回数组,不需要做数组整体比较。

2. 逻辑偏移错误:多移一位答案全错

  1. 左边界结果多加 1 循环结束后用 left + 1 作为左边界,属于对指针最终位置理解偏差。 左闭右闭模板下,命中目标时收缩右边界 right = mid - 1,循环终止时 right = left - 1,此时 left 天然指向第一个等于 target 的元素,不需要额外偏移。 结论:左边界查找,结束后直接取 left。

  2. 右边界结果多减 1 循环结束后用 right_ - 1 作为右边界,同理属于多余偏移。 命中目标时收缩左边界 left_ = mid_ + 1,循环终止时 right_ 天然指向最后一个等于 target 的元素,不需要额外减 1。 结论:右边界查找,结束后直接取 right_。

3. 边界健壮性缺失:极端用例直接崩溃

普通用例能跑通,但空数组、目标值超出数组范围的场景直接触发越界异常,属于最容易忽略的点。

  1. 只防左越界,漏掉右越界 只判断 left < 0,没判断 left >= nums.length。 触发场景:输入为空数组、target 比所有元素都大,此时 left 会等于数组长度,直接访问 nums[left] 就会抛出数组下标越界异常。 修正:越界必须双向判断:left < 0 || left >= nums.length。

  2. 越界条件写反,等于没设防 把 >= 写成 <,写成 left < nums.length,相当于把「合法条件」当成了「越界条件」,完全起不到防护作用。 记住:数组合法下标范围是 0 <= index < 数组长度,越界就是取反的结果。

  3. 忽略短路规则,先访问再判断 Java 的 || 是短路或,从左到右依次判断,前面条件成立则后面代码不执行。 必须把「索引合法性判断」放在最左侧,先拦下非法索引,绝对不会执行到 nums[left],自然不会越界。如果把数值比较放在前面,空数组场景会先访问数组再判断,直接触发异常。


三、二分查找通用自检三步法

无论是基础题还是边界变体题,写完代码按这三步自查一遍,能规避 90% 以上的低级错误:

  1. 语法自检 检查变量名是否笔误、数组返回格式是否正确、变量作用域是否合法,先保证代码能编译通过。

  2. 逻辑偏移自检

  • 基础题:确认边界移动方向正确、循环条件匹配区间定义、命中即返回
  • 边界题:左边界看 left,右边界看 right,不要额外加减偏移量
  1. 健壮性自检 先判断索引是否在合法范围内,再访问数组元素;覆盖空数组、目标值超出数组范围的极端场景。

二分查找模块的踩坑暂告一段落,后续学习新算法模块时,会持续更新本系列的踩坑记录。

← 上一篇xiaozhidaoyuanxing1下一篇 →算法踩坑-同向快慢指针

相关文章

  • 算法踩坑-相向左右指针 | 刷题踩坑连载 03约 7 分钟
  • 算法踩坑-同向快慢指针约 7 分钟

评论

需要登录账号才能发表评论。

  • 加载中…

本页内容

  • 二分查找踩坑全记录:从基础模板到边界查找,我踩过的所有雷 | 刷题踩坑连载 01
  • 一、基础二分通用坑:所有题型都要先避开的雷
  • 1. 核心逻辑类(全语言通用)
  • 2. Java 语法专属类
  • 二、进阶踩坑:左右边界查找专属(LeetCode 34 实战复盘)
  • 1. 语法细节翻车:复制代码带来的低级失误
  • 2. 逻辑偏移错误:多移一位答案全错
  • 3. 边界健壮性缺失:极端用例直接崩溃
  • 三、二分查找通用自检三步法