本文根据算法导论第三章总结,但其中加入了我对本章的一些补充,并且配合算法导论习题进行讲解。
相信本文会让你对渐近记号有更深入地理解。
一、定义介绍
对于某个比较简单的算法,我们有时候确实能够精确地分析出算法的复杂度,比如算法复杂度为5n^2+10n+6,但是事实上并不需要这样,因为当n足够大时,可以忽略掉低阶项和最高次项的系数,因此就引出了“渐近复杂度”,并且用“渐近记号”来表示“渐近复杂度”。
渐近记号包括:
(1)Θ
(theta):紧确界。 相当于"="
(2)
O
(大欧):上界。 相当于"<="
(3)
o
(小欧):非紧的上界。 相当于"<"
(4)Ω
(大omega):下界。 相当于">="
(5)
ω
(小omega):非紧的下界。 相当于">"
给出这些记号的定义:
对于定义的注意点:
(1)这些定义的前提是f(n)和g(n)是渐近非负的,渐近非负的意思是“当n趋于无穷大时,f(n)和g(n)都非负”。
(2)对于第4和第5条定义,需要注意是对于任意的c。
用集合论来表示这5个符号的关系:
从上面的图可以看出:
(1)如果f(n)=Θ(g(n)),则f(n)=
O
(g(n))且f(n)=
Ω(g(n))。
(2)如果f(n)=
o
(g(n)),则f(n)=
O
(g(n))
。
(3)如果f(n)=
ω(g(n)),则f(n)=
Ω(g(n))。
(4)如果
f(n)=
O
(g(n)),则要么是
f(n)=
o
(g(n)),要么是
f(n)=
Θ(g(n))。
(5)
如果
f(n)=
Ω(g(n))
,则要么是
f(n)=
ω
(g(n)),要么是
f(n)=
Θ(g(n))。
原因其实很简单因为:
(1)如果
f(n)=
Θ(g(n)),则根据定义一定存在c1,c2,n0,使得对于任意的n>=n0,都有c1g(n)<=f(n)<=c2g(n),因此必定存在
"c=c2,n0,使得对于任意的n>=n0,都有f(n)<=cg(n)"
"c=c1,n0,使得
对于任意的n>=n0,都有
cg(n)
<=
f(n)
"
(2)如果
f(n)=
o
(g(n)),则根据定义一定对于任意的c,都存在n0,使得任意的n>=n0,都有
f(n)<cg(n),因此必定存在“存在c,n0,使得对于任意的n>=n0,都有f(n)<=cg(n)”
(3)
如果
f(n)=
ω
(g(n)),则根据定义一定对于任意的c,都存在n0,使得任意的n>=n0,都有
cg(n)
<
f(n),因此必定存在“存在c,n0,使得对于任意的n>=n0,都有
cg(n)
<=
f(n)”
了解了这些定义后,给出一个概念:这些渐近记号表示的都是集合,比如
O
(n^2)表示的是一个集合,可以是n,1,n^2等,
因此对于这些渐近记号的使用最准确应该是“f(n)∈
O
(g(n))
”,但是一般都是写成“
f(n)=
O
(g(n))
”。
给出一些例子:
O
(n^2)可以是n,2n,1,2n^2等
。
Θ
(n^2)可以是n^2,3n^2等。
ω
(n^2)可以是n^3,n^10等,但不能是n^2。
Ω
(n^2)可以是n^2,n^3,n^10等。
o
(n^2)可以是n,1,3n等,
但不能是n^2
。
一般我们对于算法复杂度的描述都是用
O
记号,比如BellmanFord的复杂度为
O
(VE),表示对于所有的输入,都满足
O
(VE)。
二、判断两个函数的渐近关系
我们这里给出了很通用的方法,叫做“极限法”。
看到上面的方法,很多人会问“怎么没有
O
和
Ω?
”,原因很简单,因为如果
f(n)=
O
(g(n)),
则要么是
f(n)=
o
(g(n)),要么是
f(n)=
Θ(g(n))。
stirling公式:
还要注意一点:我们在证明时,一般不需要具体指出n0的值,只需要证明一定存在n0即可。(像在算法导论P27页的最后几行中,他给出了很复杂的n0,这不必深究。)
现在开始举例子。
第一个问题来源于算法导论思考题3-1。
第二个问题来源于算法导论3.2-3。
第三个问题来源于算法导论3.2-5。
第四个问题是设计函数以满足一定的条件。
第五个问题也是关于设计一个函数,他是算法导论思考题3-3(b)。
最后还要再举一个算法导论思考题3-4,因为这道题能够更清晰地理清概念。
---------------------------------------------------------------------------------------------------------------------------