二分查找动画演示

区间每次减半,边界写法决定你是对是错。

键盘:← → 单步 ·空格 播放/暂停 · R 重置 ·Home/End 到两端

二分的过程只有一件事:把候选区间对半砍。舞台上面那排格子是数组,left、right、mid 三个标注始终挂在格子上,被排除的部分会变灰;下面那排格子是区间状态,每走一步都会把 left、right、区间长度重写一遍。你会发现区间每步都在变小——一旦它停着不动,代码就已经写错了,而这正是二分最常见的事故现场。

四个题面共用同一套骨架,差别全在边界。普通查找命中就返回下标,找不到走 -1 那个出口;lower_bound 与 upper_bound 未命中时返回的是 left,也就是「该插哪儿」;旋转数组找最小则把比较对象从 target 换成 a[right],循环条件也从 left ≤ right 换成 left < right,因为 right 自己就是候选答案。把这三种出口混着写,代码看着都对,跑起来才知差一格。

二分查找演示怎么用

  • 换题面:题面下拉里切普通查找、lower_bound、upper_bound、旋转数组找最小,同一份数组分别跑一遍,边界差别一眼可见。
  • 盯区间:状态条里的区间长度只在循环开始时更新;如果连续两步它是同一个数,说明你的 mid 与收缩条件不匹配。
  • 试两端:查找目标填成比最大值还大、比最小值还小、正好等于首尾元素这三种,能覆盖住插入位置的全部边界。
  • 看溢出那步:第一轮取 mid 之后专门有一步只讲 left + (right - left) / 2 的写法,取值不变但不会先相加越界。

常见问题

二分的死循环到底出在哪?

出在收缩之后区间没真的变小。循环条件写 left < right 却按闭区间把 right ← mid - 1,或者反过来把 left ← mid(不是 mid + 1),都会让某个长度为 2 的区间原地打转。记法:条件是 ≤ 就两侧都 ±1,条件是 < 就必有一侧写 right ← mid。

为什么不写 (left + right) / 2?

两个下标都接近整数上限时,相加这一步就先溢出了,除法救不回来,负数右移得到的 mid 会跑到区间外。left + (right - left) / 2 里相加的两个数最大不超过 right - left,量级小得多,值却完全一样。Java、C++ 的 int 上这是真 bug,不是洁癖。

lower_bound 和 upper_bound 有什么区别,什么时候用?

lower_bound 返回第一个不小于 target 的位置,upper_bound 返回第一个大于 target 的位置。数组里有重复值时两者不同,相减就是 target 出现的次数;没有重复值时 upper_bound 恰好是「插到最后一个相等元素之后」。求区间长度、统计出现次数、把「找不存在的东西」变成「找该插哪儿」,都靠这两个变体。

旋转数组为什么不能直接找 target?

找最小值时你没有任何 target 可比,能用的只有区间内部的关系:a[mid] 大于 a[right],说明 mid 落在后半段,最小值在它右边;否则最小值是 mid 或更左。这一档的循环条件是 left < right,写成 left ≤ right 会让 right ← mid - 1 把最小值本身扔掉。

演示编号 D01无需安装,手机端同样可用按 Ctrl + K 搜工具与演示

顺手能用上的工具