第2章算法分析:大O符号的定义和性质
2.3 大 O 符号
2.3.1 大 O 符号的定义
大 O 符号(Big O notation),又称为渐近符号,是用于描述函数渐近行为的数学符号。更确切地说,它是用另一个(通常更简单的)函数来描述一个函数数量级的渐近上界。
大 O 符号是由德国数论学家保罗·巴赫曼在其1892年的著作《解析数论》(Analytische Zahlentheorie)首先引入的。之后经另一位德国数论学家爱德蒙·兰道的著作得到推广,因此它有时又称为兰道符号(Landau symbols)。代表“order of …”(……阶)的大 O,最初是一个大写希腊字母“Ο”(omicron),现今用的是大写英文字母“O”。
大 O 符号的本质是函数渐近行为的极限描述,其形式化定义:
给定两个定义在实数某子集上的关于 xxx 的函数 f(x)f(x)f(x) 和 g(x)g(x)g(x) ,当 xxx 趋近于无穷大时,存在正实数 MMM ,使得对于所有充分大的 xxx ,都有f(x)f(x)f(x) 的绝对值小于等于 M×g(x)M\times g(x)M×g(x) 的绝对值,那么我们就可以说,当 x→∞x\to\inftyx→∞ 时,
f(x)=O(g(x))
f(x)=O(g(x))
f(x)=O(g(x))
也就是说,假如存在正实数 MMM 和实数 x0x_0x0 ,使得对于所有的 x≥x0x\ge x_0x≥x0 ,均有:∣f(x)∣≤M∣g(x)∣|f(x)|\le M|g(x)|∣f(x)∣≤M∣g(x)∣ 成立,我们就可以认为 f(x)=O(g(x))f(x)=O(g(x))f(x)=O(g(x)) 。在很多情况下,会省略“当 xxx 趋近于无限大时”这个前提。
上述定义,用极限来表示:
当且仅当 limx→∞∣f(x)g(x)∣<∞ 时,有 f(x)=O(g(x))
当且仅当~\lim_{x\to\infty}\left|\frac{f(x)}{g(x)}\right|\lt\infty~时,有~f(x)=O(g(x))
当且仅当 x→∞limg(x)f(x)<∞ 时,有 f(x)=O(g(x))
也就是,当 x→∞x\to\inftyx→∞ 时,f(x)g(x)\frac{f(x)}{g(x)}g(x)f(x) 有上界,极限值为有限常数或未达无穷大。
例 1: 证明 T(n)=3n2+5n+2T(n)=3n^2 + 5n + 2T(n)=3n2+5n+2 是 O(n2)O(n^2)O(n2) 。
证明:
limn→∞3n2+5n+2n2=limn→∞(3+5n+2n2)=3(有限正常数)
\lim_{n\to\infty}\frac{3n² + 5n + 2}{n²}=\lim_{n\to\infty}\left(3 + \frac{5}{n} + \frac{2}{n^2}\right) = 3 (有限正常数)
n→∞limn23n2+5n+2=n→∞lim(3+n5+n22)=3(有限正常数)
因为极限存在且为有限值,所以 T(n)=O(n2)T(n) = O(n^2)T(n)=O(n2) 。
2.3.2 大 O 符号的性质
以下是大 O 符号的主要性质及其证明。证明中假设所有函数定义在自然数上,且 f(n)f(n)f(n) 非零(或仅在有限点为零)。
性质 1:(自反性)对于任意函数 f(n)f(n)f(n),有 f(n)=O(f(n))f(n) = O(f(n))f(n)=O(f(n))。
证明:
取常数 c=1c = 1c=1 和 n0=1n_0 = 1n0=1。则对于所有 n≥n0n \geq n_0n≥n0,有:∣f(n)∣≤1⋅∣f(n)∣|f(n)| \leq 1 \cdot |f(n)|∣f(n)∣≤1⋅∣f(n)∣ 。根据大 O 定义,这直接表明 f(n)=O(f(n))f(n) = O(f(n))f(n)=O(f(n)) 。
性质 2:(传递性)如果 f(n)=O(g(n))f(n) = O(g(n))f(n)=O(g(n)) 和 g(n)=O(h(n))g(n) = O(h(n))g(n)=O(h(n)),则 f(n)=O(h(n))f(n) = O(h(n))f(n)=O(h(n))。
证明:
由 f(n)=O(g(n))f(n) = O(g(n))f(n)=O(g(n)),存在常数 c1>0c_1 > 0c1>0 和 n1n_1n1 使得对于所有 n≥n1n \geq n_1n≥n1,有:∣f(n)∣≤c1⋅∣g(n)∣|f(n)| \leq c_1 \cdot |g(n)|∣f(n)∣≤c1⋅∣g(n)∣ 。
由 g(n)=O(h(n))g(n) = O(h(n))g(n)=O(h(n)),存在常数 c2>0c_2 > 0c2>0 和 n2n_2n2 使得对于所有 n≥n2n \geq n_2n≥n2,有:∣g(n)∣≤c2⋅∣h(n)∣|g(n)| \leq c_2 \cdot |h(n)|∣g(n)∣≤c2⋅∣h(n)∣ 。
取 n0=max(n1,n2)n_0 = \max(n_1, n_2)n0=max(n1,n2) 和 c=c1⋅c2c = c_1 \cdot c_2c=c1⋅c2。则对于所有 n≥n0n \geq n_0n≥n0,有:
∣f(n)∣≤c1⋅∣g(n)∣≤c1⋅(c2⋅∣h(n)∣)=(c1c2)⋅∣h(n)∣=c⋅∣h(n)∣.
|f(n)| \leq c_1 \cdot |g(n)| \leq c_1 \cdot (c_2 \cdot |h(n)|) = (c_1 c_2) \cdot |h(n)| = c \cdot |h(n)|.
∣f(n)∣≤c1⋅∣g(n)∣≤c1⋅(c2⋅∣h(n)∣)=(c1c2)⋅∣h(n)∣=c⋅∣h(n)∣.
因此, f(n)=O(h(n))f(n) = O(h(n))f(n)=O(h(n)).
性质 3:(常数倍性质)如果 f(n)=O(g(n))f(n) = O(g(n))f(n)=O(g(n)) 且 kkk 是一个常数(即 k∈R∖{0}k \in \mathbb{R} \setminus \{0\}k∈R∖{0},但 k=0k = 0k=0 时平凡成立),则 k⋅f(n)=O(g(n))k \cdot f(n) = O(g(n))k⋅f(n)=O(g(n))。
证明:
由 f(n)=O(g(n))f(n) = O(g(n))f(n)=O(g(n)),存在常数 c1>0c_1 > 0c1>0 和 n1n_1n1 使得对于所有 n≥n1n \geq n_1n≥n1,有:∣f(n)∣≤c1⋅∣g(n)∣.|f(n)| \leq c_1 \cdot |g(n)|.∣f(n)∣≤c1⋅∣g(n)∣.
取 c=∣k∣⋅c1c = |k| \cdot c_1c=∣k∣⋅c1 和 n0=n1n_0 = n_1n0=n1。则对于所有 n≥n0n \geq n_0n≥n0,有:∣k⋅f(n)∣=∣k∣⋅∣f(n)∣≤∣k∣⋅(c1⋅∣g(n)∣)=(∣k∣c1)⋅∣g(n)∣=c⋅∣g(n)∣|k \cdot f(n)| = |k| \cdot |f(n)| \leq |k| \cdot (c_1 \cdot |g(n)|) = (|k| c_1) \cdot |g(n)| = c \cdot |g(n)|∣k⋅f(n)∣=∣k∣⋅∣f(n)∣≤∣k∣⋅(c1⋅∣g(n)∣)=(∣k∣c1)⋅∣g(n)∣=c⋅∣g(n)∣
因此, k⋅f(n)=O(g(n))k \cdot f(n) = O(g(n))k⋅f(n)=O(g(n)).
性质 4:(和的性质)如果 f1(n)=O(g1(n))f_1(n) = O(g_1(n))f1(n)=O(g1(n)) 和 f2(n)=O(g2(n))f_2(n) = O(g_2(n))f2(n)=O(g2(n)),则 f1(n)+f2(n)=O(max(∣g1(n)∣,∣g2(n)∣))f_1(n) + f_2(n) = O(\max(|g_1(n)|, |g_2(n)|))f1(n)+f2(n)=O(max(∣g1(n)∣,∣g2(n)∣))。更一般地,f1(n)+f2(n)=O(∣g1(n)∣+∣g2(n)∣)f_1(n) + f_2(n) = O(|g_1(n)| + |g_2(n)|)f1(n)+f2(n)=O(∣g1(n)∣+∣g2(n)∣),且当 g1(n)g_1(n)g1(n) 和 g2(n)g_2(n)g2(n) 渐近非负时,可简化为 O(max(∣g1(n)∣,∣g2(n)∣))O(\max(|g_1(n)|, |g_2(n)|))O(max(∣g1(n)∣,∣g2(n)∣))。
证明:
由 f1(n)=O(g1(n))f_1(n) = O(g_1(n))f1(n)=O(g1(n)),存在常数 c1>0c_1 > 0c1>0 和 n1n_1n1 使得对于所有 n≥n1n \geq n_1n≥n1,有:∣f1(n)∣≤c1⋅∣g1(n)∣|f_1(n)| \leq c_1 \cdot |g_1(n)|∣f1(n)∣≤c1⋅∣g1(n)∣ .
由 f2(n)=O(g2(n))f_2(n) = O(g_2(n))f2(n)=O(g2(n)),存在常数 c2>0c_2 > 0c2>0 和 n2n_2n2 使得对于所有 n≥n2n \geq n_2n≥n2,有:∣f2(n)∣≤c2⋅∣g2(n)∣|f_2(n)| \leq c_2 \cdot |g_2(n)|∣f2(n)∣≤c2⋅∣g2(n)∣ 。
取 n0=max(n1,n2)n_0 = \max(n_1, n_2)n0=max(n1,n2) 和 c=c1+c2c = c_1 + c_2c=c1+c2。定义 g(n)=max(∣g1(n)∣,∣g2(n)∣)g(n) = \max(|g_1(n)|, |g_2(n)|)g(n)=max(∣g1(n)∣,∣g2(n)∣)。注意到对于所有 nnn,有 ∣g1(n)∣≤g(n)|g_1(n)| \leq g(n)∣g1(n)∣≤g(n) 和 ∣g2(n)∣≤g(n)|g_2(n)| \leq g(n)∣g2(n)∣≤g(n)。则对于所有 n≥n0n \geq n_0n≥n0,有:
∣f1(n)+f2(n)∣≤∣f1(n)∣+∣f2(n)∣≤c1⋅∣g1(n)∣+c2⋅∣g2(n)∣≤c1⋅g(n)+c2⋅g(n)=(c1+c2)⋅g(n)=c⋅g(n)
|f_1(n) + f_2(n)| \leq |f_1(n)| + |f_2(n)| \leq c_1 \cdot |g_1(n)| + c_2 \cdot |g_2(n)| \leq c_1 \cdot g(n) + c_2 \cdot g(n) = (c_1 + c_2) \cdot g(n) = c \cdot g(n)
∣f1(n)+f2(n)∣≤∣f1(n)∣+∣f2(n)∣≤c1⋅∣g1(n)∣+c2⋅∣g2(n)∣≤c1⋅g(n)+c2⋅g(n)=(c1+c2)⋅g(n)=c⋅g(n)
因此, f1(n)+f2(n)=O(g(n))=O(max(∣g1(n)∣,∣g2(n)∣))f_1(n) + f_2(n) = O(g(n)) = O(\max(|g_1(n)|, |g_2(n)|))f1(n)+f2(n)=O(g(n))=O(max(∣g1(n)∣,∣g2(n)∣))。
此外,因为 ∣g1(n)∣+∣g2(n)∣≤2max(∣g1(n)∣,∣g2(n)∣)|g_1(n)| + |g_2(n)| \leq 2 \max(|g_1(n)|, |g_2(n)|)∣g1(n)∣+∣g2(n)∣≤2max(∣g1(n)∣,∣g2(n)∣),所以 f1(n)+f2(n)=O(∣g1(n)∣+∣g2(n)∣)f_1(n) + f_2(n) = O(|g_1(n)| + |g_2(n)|)f1(n)+f2(n)=O(∣g1(n)∣+∣g2(n)∣) 也成立。
性质 5:(乘积性质)如果 f1(n)=O(g1(n))f_1(n) = O(g_1(n))f1(n)=O(g1(n)) 和 f2(n)=O(g2(n))f_2(n) = O(g_2(n))f2(n)=O(g2(n)),则 f1(n)⋅f2(n)=O(g1(n)⋅g2(n))f_1(n) \cdot f_2(n) = O(g_1(n) \cdot g_2(n))f1(n)⋅f2(n)=O(g1(n)⋅g2(n))。
证明:
由 f1(n)=O(g1(n))f_1(n) = O(g_1(n))f1(n)=O(g1(n)),存在常数 c1>0c_1 > 0c1>0 和 n1n_1n1 使得对于所有 n≥n1n \geq n_1n≥n1,有:∣f1(n)∣≤c1⋅∣g1(n)∣|f_1(n)| \leq c_1 \cdot |g_1(n)|∣f1(n)∣≤c1⋅∣g1(n)∣。同理可得:∣f2(n)∣≤c2⋅∣g2(n)∣|f_2(n)| \leq c_2 \cdot |g_2(n)|∣f2(n)∣≤c2⋅∣g2(n)∣ 。
取 n0=max(n1,n2)n_0 = \max(n_1, n_2)n0=max(n1,n2) 和 c=c1⋅c2c = c_1 \cdot c_2c=c1⋅c2。则对于所有 n≥n0n \geq n_0n≥n0,有:∣f1(n)⋅f2(n)∣=∣f1(n)∣⋅∣f2(n)∣≤(c1⋅∣g1(n)∣)⋅(c2⋅∣g2(n)∣)=(c1c2)⋅∣g1(n)⋅g2(n)∣=c⋅∣g1(n)⋅g2(n)∣|f_1(n) \cdot f_2(n)| = |f_1(n)| \cdot |f_2(n)| \leq (c_1 \cdot |g_1(n)|) \cdot (c_2 \cdot |g_2(n)|) = (c_1 c_2) \cdot |g_1(n) \cdot g_2(n)| = c \cdot |g_1(n) \cdot g_2(n)|∣f1(n)⋅f2(n)∣=∣f1(n)∣⋅∣f2(n)∣≤(c1⋅∣g1(n)∣)⋅(c2⋅∣g2(n)∣)=(c1c2)⋅∣g1(n)⋅g2(n)∣=c⋅∣g1(n)⋅g2(n)∣ 。
因此, f1(n)⋅f2(n)=O(g1(n)⋅g2(n))f_1(n) \cdot f_2(n) = O(g_1(n) \cdot g_2(n))f1(n)⋅f2(n)=O(g1(n)⋅g2(n)).
性质 6:(多项式性质)如果 f(n)f(n)f(n) 是一个 kkk 次多项式,即 f(n)=aknk+ak−1nk−1+⋯+a0f(n) = a_k n^k + a_{k-1} n^{k-1} + \cdots + a_0f(n)=aknk+ak−1nk−1+⋯+a0(其中 ak≠0a_k \neq 0ak=0),则 f(n)=O(nk)f(n) = O(n^k)f(n)=O(nk)。
证明:
对于足够大的 nnn(例如 n≥1n \geq 1n≥1),有 ∣ni∣≤∣nk∣|n^i| \leq |n^k|∣ni∣≤∣nk∣ 对所有 i≤ki \leq ki≤k 成立。因此:
∣f(n)∣≤∣ak∣∣nk∣+∣ak−1∣∣nk−1∣+⋯+∣a0∣≤∣ak∣∣nk∣+∣ak−1∣∣nk∣+⋯+∣a0∣∣nk∣=(∑i=0k∣ai∣)∣nk∣
|f(n)| \leq |a_k| |n^k| + |a_{k-1}| |n^{k-1}| + \cdots + |a_0| \leq |a_k| |n^k| + |a_{k-1}| |n^k| + \cdots + |a_0| |n^k| = \left( \sum_{i=0}^{k} |a_i| \right) |n^k|
∣f(n)∣≤∣ak∣∣nk∣+∣ak−1∣∣nk−1∣+⋯+∣a0∣≤∣ak∣∣nk∣+∣ak−1∣∣nk∣+⋯+∣a0∣∣nk∣=(i=0∑k∣ai∣)∣nk∣
取 c=∑i=0k∣ai∣c = \sum_{i=0}^{k} |a_i|c=∑i=0k∣ai∣ 和 n0=1n_0 = 1n0=1。则对于所有 n≥n0n \geq n_0n≥n0,有 ∣f(n)∣≤c⋅∣nk∣|f(n)| \leq c \cdot |n^k|∣f(n)∣≤c⋅∣nk∣,所以 f(n)=O(nk)f(n) = O(n^k)f(n)=O(nk).
性质 7:(对数性质)对于底数 b>1b > 1b>1 和 a>0a > 0a>0,有 logbn=O(log2n)\log_b n = O(\log_2n)logbn=O(log2n),且更一般地,(logbn)a=O(nϵ)(\log_b n)^a = O(n^\epsilon)(logbn)a=O(nϵ) 对于任意 ϵ>0\epsilon > 0ϵ>0(即对数函数增长慢于任何正幂函数)。
证明:
-
部分 1: logbn=O(logn)\log_b n = O(\log n)logbn=O(logn)。
由对数换底公式,logbn=lnnlnb\log_b n = \frac{\ln n}{\ln b}logbn=lnblnn。取 c=1∣lnb∣c = \frac{1}{|\ln b|}c=∣lnb∣1(因为 b>1b > 1b>1,所以 lnb>0\ln b > 0lnb>0) 和 n0=1n_0 = 1n0=1。则对于所有 n≥n0n \geq n_0n≥n0,有:
∣logbn∣=∣lnnlnb∣=∣lnn∣∣lnb∣≤c⋅∣lnn∣ |\log_b n| = \left| \frac{\ln n}{\ln b} \right| = \frac{|\ln n|}{|\ln b|} \leq c \cdot |\ln n| ∣logbn∣=lnblnn=∣lnb∣∣lnn∣≤c⋅∣lnn∣
因此, logbn=O(logn)\log_b n = O(\log n)logbn=O(logn)(这里 logn\log nlogn 表示自然对数)。 -
部分 2: (logbn)a=O(nϵ)(\log_b n)^a = O(n^\epsilon)(logbn)a=O(nϵ) 对于任意 ϵ>0\epsilon > 0ϵ>0。
这可以通过极限或 L’Hôpital 法则证明。考虑极限:limn→∞(logbn)anϵ\lim_{n \to \infty} \frac{(\log_b n)^a}{n^\epsilon}limn→∞nϵ(logbn)a ,
令 t=logbnt = \log_b nt=logbn,则 n=btn = b^tn=bt,当 n→∞n \to \inftyn→∞ 时 t→∞t \to \inftyt→∞,极限变为:
limt→∞ta(bt)ϵ=limt→∞tabϵt. \lim_{t \to \infty} \frac{t^a}{(b^t)^\epsilon} = \lim_{t \to \infty} \frac{t^a}{b^{\epsilon t}}. t→∞lim(bt)ϵta=t→∞limbϵtta.
由于指数函数增长快于多项式函数,该极限为 0。因此,存在 n0n_0n0 使得对于所有 n≥n0n \geq n_0n≥n0,有 (logbn)anϵ≤1\frac{(\log_b n)^a}{n^\epsilon} \leq 1nϵ(logbn)a≤1,即 ∣(logbn)a∣≤1⋅∣nϵ∣|(\log_b n)^a| \leq 1 \cdot |n^\epsilon|∣(logbn)a∣≤1⋅∣nϵ∣。所以 (logbn)a=O(nϵ)(\log_b n)^a = O(n^\epsilon)(logbn)a=O(nϵ).
注意:
-
大 O 符号不具有对称性:即 f(n)=O(g(n))f(n) = O(g(n))f(n)=O(g(n)) 不一定意味着 g(n)=O(f(n))g(n) = O(f(n))g(n)=O(f(n))。如果两者同时成立,则记作 f(n)=Θ(g(n))f(n) = \Theta(g(n))f(n)=Θ(g(n))(Theta 符号),表示 fff 和 ggg 有相同的渐近增长率。
-
大 O 符号关注上界,且忽略常数因子和低阶项,这使其适用于描述大规模输入下的性能。
-
不要写成 T(n)=O(2n2)T(n)=O(2n^2)T(n)=O(2n2) 或 T(n)=O(n2+n)T(n)=O(n^2+n)T(n)=O(n2+n) 。这两种的正确表示是 T(n)=O(n2)T(n)=O(n^2)T(n)=O(n2) 。
-
不表示 T(n)≤O(f(n))T(n)\le O(f(n))T(n)≤O(f(n)) ,因为对大 O 记号的定义中已经隐含了不等关系。
-
T(n)≥O(f(n))T(n)\ge O(f(n))T(n)≥O(f(n)) 的表示是错误的,没有意义。
大 O 符号体现了对函数总体渐进趋势的关注和刻画,在后续进行算法时间复杂度和空间复杂度分析中将大显身手。
以上一直在书写大 O 符号,如果用口语表达,怎么读?以 O(n)O(n)O(n) 为例,可以读作“大 O n”,也可以读作 “O n”。