这个部分尝试从校内课程入手,然后参考学习算法导论内容,继续开阔自己的眼界。校内课程对应的是高级算法设计,学习的时候多总结、多练习、多回忆应该是有效果的,毕竟这学期时间很紧迫。
本章主要进行算法复杂性的分析,学习基本的空间复杂度和时间复杂度,并且掌握一些基本的快速估计复杂度的定理、方法。
算法效率分析基础
算法分析是对一个算法需要多少计算时间和存储空间做定量的分析。
分析框架
输入规模度量
- 算法的时间效率和空间效率都用输入规模的函数进行度量
- 对相同的大小的输入实例具有相同的分析结果
- 对于所有的算法,对于规模更大的输入都需要更长的运行时间
- 经常使用一个输入规模n为参数的函数来研究算法的效率
运行时间的度量单位
- 用算法的基本操作(算法中最重要的操作)的执行次数来度量算法的时间效率
- 基本操作通常是算法的最内层循环中最费时的操作
- 算法运行时间的估计:
T ( n ) ≈ c o p C ( n ) T(n)\approx c_{op}C(n) T(n)≈copC(n)
n是该算法的输入规模
c o p c_{op} cop 是特定计算机上一个算法基本操作的执行时间
C(n)是该算法需要执行的基本操作次数
算法的最优、最差、平均效率
- 最差效率是指在输入规模为n的时候,算法在最坏情况下的效率
- 最优效率是指在输入规模为n时,算法在最优情况下的效率
- 平均效率是指在“典型”或“随机”输入的情况下,算法具有的行为(效率)
增长次数
- 小规模输入在运行时间上的差别不足以将高效的算法和低效的算法区分开来
- 指数级操作次数的算法,只能解决规模非常小的问题
指数与多项式
2 n 2^n 2n 与 n 2 n^2 n2 相比,指数的增长速度是很快的,在算法中应该尽量避免。
数量级的差别
在很多时候,我们认为 n n n 和 n 2 n^2 n2之间的差异是比较大的,而n和5n之间的差异是较小的甚至可以忽略不计,因此引入渐进表达式来解决这个问题。
渐进表达式
常数间差异较小
渐进表达式的核心在于忽略掉常数。
渐进分析符号
渐进上界符号
渐近上界符号
O
O
O,存在正常数
c
c
c和
n
0
n_0
n0使得对所有
n
≥
n
0
n\geq n_0
n≥n0,有
f
(
n
)
≤
c
g
(
n
)
f(n) \leq cg(n)
f(n)≤cg(n)
记为
f
(
n
)
∈
O
(
g
(
n
)
)
f(n) ∈O(g(n))
f(n)∈O(g(n))
渐进下界符号
渐进下界符号
Ω
\Omega
Ω,存在正常数
c
c
c 和
n
0
n_0
n0 使得对所有的
n
≥
n
0
n \geq n_0
n≥n0有:
f
(
n
)
≥
c
g
(
n
)
f(n) \geq cg(n)
f(n)≥cg(n)
记为
f
(
n
)
∈
Ω
(
g
(
n
)
)
f(n) \in \Omega(g(n))
f(n)∈Ω(g(n))
渐进近界符号
渐进近界符号
θ
\theta
θ, 存在正常数
c
1
c_1
c1,
c
2
c_2
c2和
n
0
n_0
n0使得对所有的
n
≥
n
0
n \geq n_0
n≥n0都有:
c
2
g
(
n
)
≤
f
(
n
)
≤
c
1
g
(
n
)
c_2g(n) \leq f(n) \leq c_1g(n)
c2g(n)≤f(n)≤c1g(n)
记为
f
(
n
)
∈
Θ
(
g
(
n
)
)
f(n) \in \Theta(g(n))
f(n)∈Θ(g(n))
非紧上界记号
非紧上界记号 o o o, o ( g ( n ) ) o(g(n)) o(g(n)) = { f ( n ) f(n) f(n) | 对于任何正常数 c > 0 c > 0 c>0,存在正数 n 0 > 0 n_0 >0 n0>0使得对所有 n ≥ n 0 n \geq n_0 n≥n0有: 0 ≤ f ( n ) < c g ( n ) 0 \leq f(n) < cg(n) 0≤f(n)<cg(n) },等价于 f ( n ) / g ( n ) → 0 f(n) / g(n) \to 0 f(n)/g(n)→0 ,as n → ∞ n \to \infty n→∞。
非紧下界记号
非紧下界记号
ω
\omega
ω,
(
g
(
n
)
)
(g(n))
(g(n)) = {
f
(
n
)
f(n)
f(n) | 对于任何正常数
c
>
0
c>0
c>0,存在正数
n
0
>
0
n_0 >0
n0>0使得对所有
n
≥
n
0
n \geq n_0
n≥n0有:
0
≤
c
g
(
n
)
<
f
(
n
)
0 \leq cg(n) < f(n)
0≤cg(n)<f(n) }
等价于
f
(
n
)
/
g
(
n
)
→
∞
f(n) / g(n) \to \infty
f(n)/g(n)→∞ ,as
n
→
∞
n \to \infty
n→∞。
f
(
n
)
∈
(
g
(
n
)
)
⇔
g
(
n
)
∈
o
(
f
(
n
)
)
f(n) \in (g(n)) \Leftrightarrow g(n) \in o (f(n))
f(n)∈(g(n))⇔g(n)∈o(f(n))
渐进符号的特性
定理:如果 t 1 ( n ) ∈ O ( g 1 ( n ) ) t_1(n) \in O(g_1(n)) t1(n)∈O(g1(n))并且 t 2 ( n ) ∈ O ( g 2 ( n ) ) t_2(n) \in O(g_2(n)) t2(n)∈O(g2(n)),则 t 1 ( n ) + t 2 ( n ) ∈ O ( m a x ( g 1 ( n ) , g 2 ( n ) ) t_1(n) + t_2(n) \in O(max{(g_1(n), g_2(n)}) t1(n)+t2(n)∈O(max(g1(n),g2(n))
- 对于渐进符号 Ω \Omega Ω, Θ \Theta Θ,该定理也成立
- 该定理表明:当算法由两个连续执行部分组成时,该算法的整体效率由具有较大增长次数的那部分所决定
渐进分析中函数的比较
这个部分可以类比大小的比较进行:
f
(
n
)
=
O
(
g
(
n
)
)
≈
a
≤
b
f
(
n
)
=
Ω
(
g
(
n
)
)
≈
a
≥
b
f
(
n
)
=
Θ
(
g
(
n
)
)
≈
a
=
b
f
(
n
)
=
o
(
g
(
n
)
)
≈
a
<
b
f
(
n
)
=
ω
(
g
(
n
)
)
≈
a
>
b
f(n) = O(g(n)) \approx a \leq b \\ f(n) = \Omega(g(n)) \approx a \geq b \\ f(n) = \Theta(g(n)) \approx a = b \\ f(n) = o(g(n)) \approx a < b \\ f(n) = \omega(g(n)) \approx a > b
f(n)=O(g(n))≈a≤bf(n)=Ω(g(n))≈a≥bf(n)=Θ(g(n))≈a=bf(n)=o(g(n))≈a<bf(n)=ω(g(n))≈a>b
渐进符号的性质
传递性
f ( n ) = Θ ( g ( n ) ) , g ( n ) = Θ ( h ( n ) ) ⇒ f ( n ) = Θ ( h ( n ) ) f ( n ) = O ( g ( n ) ) , g ( n ) = O ( h ( n ) ) ⇒ f ( n ) = O ( h ( n ) ) f ( n ) = Ω ( g ( n ) ) , g ( n ) = Ω ( h ( n ) ) ⇒ f ( n ) = Ω ( h ( n ) ) f ( n ) = o ( g ( n ) ) , g ( n ) = o ( h ( n ) ) ⇒ f ( n ) = o ( h ( n ) ) f ( n ) = ω ( g ( n ) ) , g ( n ) = ω ( h ( n ) ) ⇒ f ( n ) = ω ( h ( n ) ) f(n)= \Theta(g(n)),g(n)= \Theta(h(n)) \Rightarrow f(n)= \Theta(h(n)) \\ f(n)= O(g(n)), g(n)= O(h(n)) \Rightarrow f(n)= O(h(n))\\ f(n)= \Omega(g(n)), g(n)= \Omega(h(n)) \Rightarrow f(n)= \Omega(h(n))\\ f(n)= o(g(n)), g(n)= o(h(n)) \Rightarrow f(n)= o(h(n)) \\ f(n)= \omega(g(n)), g(n)= \omega(h(n)) \Rightarrow f(n)= \omega(h(n)) f(n)=Θ(g(n)),g(n)=Θ(h(n))⇒f(n)=Θ(h(n))f(n)=O(g(n)),g(n)=O(h(n))⇒f(n)=O(h(n))f(n)=Ω(g(n)),g(n)=Ω(h(n))⇒f(n)=Ω(h(n))f(n)=o(g(n)),g(n)=o(h(n))⇒f(n)=o(h(n))f(n)=ω(g(n)),g(n)=ω(h(n))⇒f(n)=ω(h(n))
反身性
f ( n ) = Θ ( f ( n ) ) f ( n ) = O ( f ( n ) ) f ( n ) = Ω ( f ( n ) ) f(n)= \Theta(f(n)) \\ f(n)= O(f(n)) \\ f(n)= \Omega(f(n)) f(n)=Θ(f(n))f(n)=O(f(n))f(n)=Ω(f(n))
对称性
f ( n ) = Θ ( g ( n ) ) ⇔ g ( n ) = Θ ( f ( n ) ) f(n) = \Theta(g(n)) \Leftrightarrow g(n)= \Theta(f(n)) f(n)=Θ(g(n))⇔g(n)=Θ(f(n))
互对称性
f ( n ) = O ( g ( n ) ) ⇔ g ( n ) = Ω ( f ( n ) ) f ( n ) = o ( g ( n ) ) ⇔ g ( n ) = ω ( f ( n ) ) f(n)= O(g(n)) \Leftrightarrow g(n)= \Omega(f(n)) \\ f(n)= o(g(n)) \Leftrightarrow g(n)= \omega(f(n)) f(n)=O(g(n))⇔g(n)=Ω(f(n))f(n)=o(g(n))⇔g(n)=ω(f(n))
算术运算
f ( n ) + g ( n ) = O ( f ( n ) + g ( n ) ) f ( n ) ∗ g ( n ) = O ( f ( n ) ∗ g ( n ) ) c f ( n ) = O ( f ( n ) ) g ( n ) = O ( f ( n ) ) ⇔ f ( n ) + g ( n ) = O ( f ( n ) ) f(n)+g(n)= O(f(n)+g(n)) \\\\ f(n)*g(n) = O(f(n)*g(n)) \\\\ cf(n) = O(f(n)) \\\\ g(n)= O(f(n)) \Leftrightarrow f(n)+g(n) = O(f(n)) f(n)+g(n)=O(f(n)+g(n))f(n)∗g(n)=O(f(n)∗g(n))cf(n)=O(f(n))g(n)=O(f(n))⇔f(n)+g(n)=O(f(n))
习题
1、给定 f 1 ( n ) = O ( f ( n ) ) f1(n) = O(f(n)) f1(n)=O(f(n)) , g 1 ( n ) = O ( g ( n ) ) g_1(n) = O(g(n)) g1(n)=O(g(n)) ,请证明 f 1 ( n ) + g 1 ( n ) = O ( f ( n ) + g ( n ) ) f_1(n) +g_1(n) = O(f(n)+g(n)) f1(n)+g1(n)=O(f(n)+g(n))
2、已知 g ( n ) = O ( f ( n ) ) g(n)= O(f(n)) g(n)=O(f(n)) ,证明 f ( n ) + g ( n ) = O ( f ( n ) ) f(n)+g(n) = O(f(n)) f(n)+g(n)=O(f(n))
基本效率类型
常量( c c c) < 对数( l o g n logn logn) < l o g 2 n log^2n log2n < 线性( n n n) < n l o g n nlogn nlogn < 平方( n 2 n^2 n2) <立方( n 3 n^3 n3) < 指数( 2 n 2^n 2n) < 阶乘( n ! n! n!)
多项式
给定一个非负整数
d
d
d,
n
n
n的
d
d
d次多项式为具有以下形式的一个函数
p
(
n
)
p(n)
p(n):
p
(
n
)
=
∑
i
=
0
d
a
i
n
i
p(n) = \sum_{i=0}^d a_i n^i
p(n)=i=0∑daini
其中常量
a
0
,
a
1
,
.
.
.
,
a
d
a_0,a_1,...,a_d
a0,a1,...,ad是多项式的系数且
a
i
≠
0
a_i \ne 0
ai=0。一个多项式为渐进正的当且仅当
a
d
>
0
a_d > 0
ad>0。对于一个
d
d
d次渐进正的多项式
p
(
n
)
p(n)
p(n),有
p
(
n
)
=
Θ
(
n
d
)
p(n) = \Theta(n^d)
p(n)=Θ(nd)。对任意实常量
a
≥
0
a \geq 0
a≥0,函数
n
a
n^a
na单调递增,对任意实常量
a
≤
0
a \leq 0
a≤0,函数
n
a
n^a
na单调递减。若对某个常量
k
k
k,有
f
(
n
)
=
O
(
n
k
)
f(n) = O(n^k)
f(n)=O(nk),则称函数
f
(
n
)
f(n)
f(n)是多项式有界的。
指数
可以通过下边儿的极限,讲多项式与指数的增长率互相关联。对所有使得
a
>
1
a > 1
a>1的实常量
a
a
a和
b
b
b,有
lim
n
→
∞
n
b
a
n
=
0
\lim_{n \to \infty} \frac{n^b}{a^n} = 0
n→∞limannb=0
根据此可以得知:
n
b
=
o
(
a
n
)
n^b = o(a^n)
nb=o(an)
因此,任意底大于1的指数函数比任意多项式函数增长得快。
对数
若对某个常量
k
k
k,
f
(
n
)
=
O
(
lg
d
n
)
f(n) = O(\lg ^d n)
f(n)=O(lgdn)则称函数
f
(
n
)
f(n)
f(n)是多对数有界的。可以通过下列极限,将多项式与多对数的增长互相关联:
lim
n
→
∞
lg
b
n
(
2
a
)
lg
n
=
lim
n
→
∞
lg
b
n
n
a
=
0
\lim_{n \to \infty} \frac{\lg^bn}{(2^a)^{\lg n}} = \lim_{n \to \infty} \frac{\lg^bn}{n^a} = 0
n→∞lim(2a)lgnlgbn=n→∞limnalgbn=0
根据这个极限,我们可以得到:对任意常量
a
>
0
a>0
a>0,
lg
b
n
=
o
(
n
a
)
\lg^bn = o(n^a)
lgbn=o(na)
因此,任意正的多项式函数都比任意多对数函数增长得快。
阶乘
记号
n
!
n!
n!定义为对整数
n
≥
0
n \geq 0
n≥0,有
n
!
=
{
1
,若
n
=
0
n
(
n
−
1
)
!
,若
n
>
0
n! = \begin{cases} 1, 若 n=0\\ n(n-1)!,若n>0\\ \end{cases}
n!={1,若n=0n(n−1)!,若n>0
阶乘函数的一个弱上界是
n
!
≤
n
n
n! \leq n^n
n!≤nn,因为在阶乘中,
n
n
n项的每项最多为
n
n
n。斯特林近似公式
n
!
=
2
π
n
(
n
e
)
n
(
1
+
Θ
(
1
n
)
)
n! = \sqrt{2 \pi n}(\frac{n}{e})^n(1+\Theta(\frac{1}{n}))
n!=2πn(en)n(1+Θ(n1))
给出了一个更紧确的上界和下界,其中
e
e
e是自然对数的地。
n
!
=
o
(
n
n
)
n
!
=
ω
(
2
n
)
lg
(
n
!
)
=
Θ
(
n
lg
n
)
n! = o(n^n)\\ n! = \omega(2^n)\\ \lg(n!) = \Theta(n\lg n)
n!=o(nn)n!=ω(2n)lg(n!)=Θ(nlgn)
多重函数
我们使用记号
f
(
i
)
(
n
)
f^{(i)}(n)
f(i)(n)来表示函数
f
(
n
)
f(n)
f(n)重复
i
i
i次作用于一个初值
n
n
n上。形式化的,假设
f
(
n
)
f(n)
f(n)为实数集上的一个函数。对非负整数
i
i
i,我们递归的定义:
f
(
i
)
(
n
)
=
{
n
若
i
=
0
f
(
f
(
i
−
1
)
(
n
)
)
若
i
>
0
f^{(i)}(n) = \begin{cases} n \quad 若 i = 0 \\ f(f^{(i-1)}(n)) \quad 若i>0 \end{cases}
f(i)(n)={n若i=0f(f(i−1)(n))若i>0
例如,若
f
(
n
)
=
2
n
f(n) = 2n
f(n)=2n,则
f
(
i
)
=
2
i
n
f^{(i)} = 2^i n
f(i)=2in。
多重对数函数
我们使用
lg
∗
n
\lg ^* n
lg∗n(读作“
log
\log
log星
n
n
n”)来表示多重对数,定义多重函对数函数为
lg
∗
n
=
m
i
n
{
i
≥
0
:
lg
(
i
)
≤
1
}
\lg^* n = min\{ i \geq 0: \lg^{(i)} \leq 1\}
lg∗n=min{i≥0:lg(i)≤1}
注意:区分
lg
(
i
)
n
\lg ^ {(i)}n
lg(i)n(从参数
n
n
n开始,连续应用对数函数
i
i
i次)与
lg
i
n
\lg^i n
lgin(
n
n
n的对数的
i
i
i次幂)。多重对数是一个增长非常慢的函数。
渐进增长率比较的三种方法
1、定义法
找到正常数
c
c
c和
n
0
n_0
n0使得对所有
n
≥
n
0
n \geq n_0
n≥n0有
f
(
n
)
≤
c
g
(
n
)
f(n) \leq cg(n)
f(n)≤cg(n),则
f
(
n
)
=
O
(
g
(
n
)
)
f(n) = O(g(n))
f(n)=O(g(n))
2、极限法
比较两个函数 f ( n ) f(n) f(n)和 g ( n ) g(n) g(n)的渐近增长率时,可以对两个函数相除,然后令变量 n n n趋向于无穷,看这个极限值是无穷大还是一个大于零的常数还是趋向于0。
比如,当
lim
n
→
∞
f
(
n
)
g
(
n
)
=
0
\lim_{n \to \infty} \frac{f(n)}{g(n)} = 0
n→∞limg(n)f(n)=0
则
f
(
n
)
=
O
(
g
(
n
)
)
f(n) = O(g(n))
f(n)=O(g(n))
前两种情况意味着t(n) ∈ O(g(n))
后两种情况意味着t(n) ∈ Ω(g(n))
第二种情况意味着t(n) ∈ Θ(g(n))
3、取对数法
对于比较难的比较的两个函数,我们可以对它们同时取对数后再进行比较,比如:
(
l
o
g
n
)
3
n
2
n
log
n
(logn)^{3n} \quad 2^{n \log n}
(logn)3n2nlogn
例题
对下列函数按渐进关系O从小到大排列:
f
1
(
n
)
=
1
0
n
f
2
(
n
)
=
n
1
/
3
f
3
(
n
)
=
n
n
f
4
(
n
)
=
l
o
g
2
n
f
5
(
n
)
=
2
l
o
g
2
n
f_1(n) = 10^n \quad f_2(n) = n ^{1/3} \\ f_3(n) = n^n \quad f_4(n) = log_2 n \\ f_5(n) = 2^{\sqrt{log_2 n}}
f1(n)=10nf2(n)=n1/3f3(n)=nnf4(n)=log2nf5(n)=2log2n