女孩和机器人一起思考

一起动脑筋 · 先看一个小故事

机器人把 16 个候选位置折半,女孩发现只需几次,范围就很小了。

把过程摊开来看

沿着编号看一遍,再用自己的话讲一遍
  1. 16 个候选缩到约 8
  2. 8 个候选缩到约 4
  3. 4 个候选缩到约 2
  4. 2 个候选缩到约 1

每次把候选数量缩小到大约一半,所需轮数增长很慢,这叫对数级增长。

数据翻倍,通常只多一次折半。图画的是候选规模的变化,不是某个具体实现的精确比较记录。

每次为什么能排除一半?

只在从小到大排列的卡片中找 7。灰色卡片表示已经排除。

第 1 步 · 看中间下标 2
13579

中间值 5 小于 7;它和左侧都不可能是目标。

第 2 步 · 留下右边两个
×××79

按向下取整的中间下标,比较下标 3 的值 7。

第 3 步 · 找到目标
×××7 ✓9

返回下标 3,即第四张卡;9 不必再检查。

01二分查找每次做了什么?

它不是只检查一个元素,更重要的是每次比较后能排除大约一半候选。

nn/2n/4n/8...

021024 个元素需要减半多少次?

1024512256→ ... →1

因为:

1024 = 2^10

所以大约需要 10 次减半。

03log₂n 在说什么?

log₂ n 可以理解成:

2 要乘自己多少次,才能到达 n?

也等价于问:n 连续除以 2,大约多少次能缩到 1。

04为什么写 O(log n) 而不是 O(log₂ n)?

因为不同底数的对数只差一个常数倍:

log₂n = 常数 × log₁₀n

大 O 渐近分析会忽略这种固定常数倍,因此通常直接写 O(log n)。

05O(log n) 有多慢增长?

nlog₂n 约为
102410
1,048,57620
约 10 亿30

输入规模增加很多倍,操作次数只增加一点点。

06只要每次减半就是 O(log n) 吗?

如果每一轮做的额外工作是 O(1),而问题规模每轮按固定比例缩小,那么常见结果确实是 O(log n)。

如果每一轮内部还做大量工作,总复杂度还要把那部分计算进去。

你已经知道了什么

  • 二分查找每轮把候选范围大约减半。
  • 从 n 连续减半到 1 需要约 log₂n 轮。
  • 因此二分查找是 O(log n)。
  • 大 O 中通常省略对数底数。
  • O(log n) 增长非常缓慢。

下一篇:怎样让一个很慢的程序变快?

轮到你来试一试

16 个候选变成 32 个,折半轮数大约翻倍吗?

想好了吗?点开看解释

不是,通常只增加一轮:先把 32 缩到约 16,再走原来的过程。