O(1)这种写法源自数学中的“大O符号”(Big O notation)。
简单的总结:
-
O:代表 “量级”(Order),描述的是趋势。
-
1:代表 “常数”(Constant),描述的是跟输入规模没关系。
下面详细解释每一个部分:
一、 “O” 是什么意思?
“O” 代表Order of magnitude(数量级)。
它的核心作用是描述“变化趋势”,而不是计算具体的“数值”。
-
它不关心:你的代码到底是跑了 0.01 秒还是 10 秒。
-
它只关心:当数据量($N$)变大时,你的代码变慢的速度有多快?
想象你在吹气球:
-
如果数据量增加一倍,耗时也增加一倍,那是 $O(N)$。
-
如果数据量增加一倍,耗时爆炸式增长(增加平方倍),那是 $O(N^2)$。
-
如果数据量增加一倍,耗时完全不变,那就是我们今天要讲的 $O$……
二、 “1” 是什么意思?
“1” 在这里代表“常数”(Constant)。
这里的$1$ 不是指“1秒”,也不是指“1行代码”或“1个步骤”。
它是一个数学代号,意思是:运算次数是固定的。
为什么用数字1?
在数学公式中,任何常数(比如 5、100、9999)相对于变量 $N$ 来说,都可以简化看作 $1 \times \text{常数}$。
在算法复杂度理论中,我们忽略系数。
-
如果是 3 个步骤,我们记作 $O(1)$。
-
如果是 100 个步骤,我们依然记作 $O(1)$。
-
如果是 2,000,000 个步骤,只要这个数字不随数据量 $N$ 变化,它依然是 $O(1)$。
形象理解:
你可以把$1$理解为$N^0$(N 的 0 次方)。
数学上,任何数的 0 次方都等于 1。
这意味着:数据量 $N$无论是多少,对我的运算时间都没有任何影响。
三、 为什么这么取名字? (命名由来)
这个符号最早由德国数学家保罗·巴赫曼(Paul Bachmann)和埃德蒙·兰道(Edmund Landau)引入,所以也叫“兰道符号”。
-
O 取自德语单词 Ordnung(英语 Order),意思是“阶”或“级”。
-
括号里的内容(如$1$,$N$,$N^2$)代表了函数增长的主导项。
当我们写$T(n) = O(1)$ 时,数学上的严格定义是:
存在一个常数$C$,使得当$N$足够大时,算法的运行时间永远小于$C \times 1$。
用人话说:
算法的耗时有一个“封顶”,这个封顶值是固定的,不会因为处理的数据变多而被冲破。
四、 具体的$O(1)$例子
为了让你彻底明白,我们对比两个场景:
场景A:非$O(1)$—— 数钱
给你一堆钱($N$ 张),让你数数有多少张。
-
10 张钱$\to$你要数10 次。
-
100 张钱$\to$你要数100 次。
-
耗时随$N$ 增长。这就不是 $O(1)$,这是 $O(N)$。
场景B:$O(1)$—— 查字典的页码
给你一本字典,字典有一个目录:
-
“A” 在第10 页。
-
“B” 在第50 页。
-
...
-
“Z” 在第1000 页。
现在任务是:翻到“Z”那一部分。
-
情况 1(字典很薄,只有100页):你看目录,看到“Z”在 90 页,直接翻过去。操作次数:1次。
-
情况 2(字典巨厚,有100万页):你看目录,看到“Z”在 990,000 页,直接翻过去。操作次数:还是1次。
这就是$O(1)$。
无论字典厚度($N$)怎么变,你“查目录并翻开”这个动作的复杂度是不变的。
总结
-
O (Order):我要衡量的是变慢的趋势。
-
1 (Constant):完全不随数据量变慢。哪怕数据量由 1 变成了 100 亿,我的处理时间依然是那样,稳如泰山。