(三)递归函数复杂度分析——算法设计与分析
本文介绍4种递归函数时间复杂度的求解方法:迭代展开、变量代换、Master定理、先猜后证。
递归算法是我们经常遇到的算法,如何分析其时间复杂度是个问题。本文介绍4种求解方法。
一、递归函数复杂度求解
1. 迭代方法
迭代地展开递归式,将其转化为和式,然后求解。
举个例子:
T
(
n
)
=
2
T
(
n
2
)
+
c
n
T(n)=2T(\frac{n}{2} )+cn
T(n)=2T(2n)+cn
首先将其迭代展开:
T
(
n
)
=
2
T
(
n
2
)
+
c
n
=
2
2
T
(
n
2
2
)
+
c
n
+
c
n
=
2
3
T
(
n
2
3
)
+
c
n
+
c
n
+
c
n
=
…
=
2
k
T
(
n
2
k
)
+
k
c
n
\begin{aligned} T(n)&=2T(\frac{n}{2} )+cn\\ &=2^2T(\frac{n}{2^2} )+cn+cn\\ &=2^3T(\frac{n}{2^3} )+cn+cn+cn\\ &=\dots \\ &=2^kT(\frac{n}{2^k} )+kcn\\ \end{aligned}
T(n)=2T(2n)+cn=22T(22n)+cn+cn=23T(23n)+cn+cn+cn=…=2kT(2kn)+kcn
接下来是关键一步,我们假设当展开到第
k
k
k次时,递归结束,即
n
2
k
=
1
\frac{n}{2^k} =1
2kn=1,接下来要将未知数
k
k
k全部替换成
n
n
n,则有:
n
2
k
=
1
⇒
n
=
2
k
T
(
n
)
=
2
k
T
(
n
2
k
)
+
k
c
n
=
2
k
T
(
1
)
+
k
c
n
=
n
T
(
1
)
+
c
n
log
n
=
Θ
(
n
log
n
)
\frac{n}{2^k} =1 \Rightarrow n = 2^k\\ \begin{aligned} T(n)&=2^kT(\frac{n}{2^k} )+kcn\\ &=2^kT(1)+kcn \\ &=nT(1)+cn \log n\\ &=\Theta(n\log n)\\ \end{aligned}
2kn=1⇒n=2kT(n)=2kT(2kn)+kcn=2kT(1)+kcn=nT(1)+cnlogn=Θ(nlogn)
至此求解完成,
T
(
n
)
T(n)
T(n)的时间复杂度为
Θ
(
n
log
n
)
\Theta(n\log n)
Θ(nlogn),如果要求不高的话,可以写低阶函数
O
O
O。
需要说明的一点是,我们通常将 log 2 n \log _{2}{n} log2n写作 log n \log n logn。
总结一下:
迭代法求解递归函数复杂度:
- 迭代展开,将递归函数展成具有规律的和式。
- 假设第 k k k次展开递归结束,达到递归终点 T ( 1 ) T(1) T(1)。
- 利用 k k k与 n n n的关系,将和式里的 k k k全部替换为 n n n的表达式。
- 求解时间复杂度。当式子复杂不易求解时,可以采用放缩的方式来求上界\下界。
2. 变量代换法
可能有某些递归方程,通过变量代换后可以变成我们熟悉的样子,此时可以用这种方法。
举个例子:
T
(
n
)
=
2
T
(
n
2
+
17
)
+
n
T(n)=2T(\frac{n}{2} +17)+n
T(n)=2T(2n+17)+n
我们发现,这个式子好像和我们刚才求结果的式子的形式差不多,我们做一下处理,令
n
=
m
+
34
n=m+34
n=m+34:
n
=
m
+
34
T
(
n
)
=
2
T
(
n
2
+
17
)
+
n
⇒
T
(
m
+
34
)
=
2
T
(
m
2
+
34
)
+
m
+
34
n=m+34\\ \begin{aligned} T(n)&=2T(\frac{n}{2} +17)+n\\ \Rightarrow T(m+34)&=2T(\frac{m}{2} +34)+m+34\\ \end{aligned}
n=m+34T(n)⇒T(m+34)=2T(2n+17)+n=2T(2m+34)+m+34
令
T
(
m
+
34
)
=
S
(
m
)
T(m+34) = S(m)
T(m+34)=S(m),则有:
S
(
m
)
=
2
S
(
m
2
)
+
m
+
34
S(m)=2S(\frac{m}{2})+m+34
S(m)=2S(2m)+m+34
此时我们便可以依照上个例子,直接给出结论:
S
(
m
)
=
Θ
(
m
log
m
)
S(m)=\Theta (m\log m)
S(m)=Θ(mlogm),由
n
=
m
+
34
n=m+34
n=m+34可知,
T
(
n
)
=
Θ
(
n
log
n
)
T(n)=\Theta (n\log n)
T(n)=Θ(nlogn)。
总结一下:
变量代换求解递归函数复杂度:
- 观察递归函数形式特点,发现与已经做过的类似。
- 找到合适的变量进行代换。
- 求解代换后的时间复杂度。
- 转化为原式的时间复杂度
此方法的缺点很明显:当看不出来合适的变量代换时便不能使用;但是对于有些题目而言,不使用此方法的话,很难求解,举一个例子:
求
解
:
T
(
n
)
=
2
T
(
n
1
2
)
+
log
n
令
n
=
2
m
,
则
有
:
T
(
2
m
)
=
2
T
(
2
m
2
)
+
m
令
T
(
2
m
)
=
S
(
m
)
,
则
:
S
(
m
)
=
2
S
(
m
2
)
+
m
⇒
S
(
m
)
=
Θ
(
m
log
m
)
⇒
T
(
n
)
=
Θ
(
log
n
log
log
m
)
求解:T(n)=2T(n^{\frac{1}{2}})+\log n \\ 令n=2^m,则有:\\ T(2^m)=2T(2^{\frac{m}{2}})+m \\ 令T(2^m)=S(m),则:\\ S(m)=2S(\frac{m}{2})+m\\ \Rightarrow S(m)=\Theta(m\log m)\\ \Rightarrow T(n)=\Theta(\log n \log\log m)
求解:T(n)=2T(n21)+logn令n=2m,则有:T(2m)=2T(22m)+m令T(2m)=S(m),则:S(m)=2S(2m)+m⇒S(m)=Θ(mlogm)⇒T(n)=Θ(lognloglogm)
3. Master定理
该定理用于求解 T ( n ) = a T ( n b ) + f ( n ) T(n)=aT(\frac{n}{b})+f(n) T(n)=aT(bn)+f(n)型函数,其中 a ≥ 1 , b > 0 a\ge 1,b>0 a≥1,b>0, f ( n ) f(n) f(n)为正函数。
Master定理
当满足以上条件时,有以下结论:
- 若 f ( n ) = O ( n log b a − ε ) , ε > 0 f(n)=O(n^{\log_ba-\varepsilon}),\varepsilon>0 f(n)=O(nlogba−ε),ε>0,则 T ( n ) = Θ ( n l o g b a ) T(n)=\Theta(n^{log_ba}) T(n)=Θ(nlogba)
- 若 f ( n ) = Θ ( n log b a ) f(n)=\Theta(n^{\log_ba}) f(n)=Θ(nlogba),则 T ( n ) = Θ ( n l o g b a log n ) T(n)=\Theta(n^{log_ba}\log n) T(n)=Θ(nlogbalogn)
- 若 f ( n ) = Ω ( n log b a + ε ) , ε > 0 f(n)=\Omega(n^{\log_ba+\varepsilon}),\varepsilon>0 f(n)=Ω(nlogba+ε),ε>0,且对于所有充分大的 n n n有 a f ( n b ) ≤ C f ( n ) , C < 1 af(\frac{n}{b})\leq Cf(n),C<1 af(bn)≤Cf(n),C<1,则 T ( n ) = Θ ( f ( n ) ) T(n)=\Theta(f(n)) T(n)=Θ(f(n))
想必大家看到这一大堆必然头疼,我们直观地来看,上述定理描述了以下含义:
比较 f ( n ) f(n) f(n)与 n log b a n^{\log_b a} nlogba阶数的大小:
- 若 f ( n ) f(n) f(n)小于 n log b a n^{\log_b a} nlogba,且是多项式地小于,即对于某个常数 ε > 0 , f ( n ) = O ( n log b a − ε ) \varepsilon >0,f(n)=O(n^{\log_ba-\varepsilon}) ε>0,f(n)=O(nlogba−ε),则有 T ( n ) = Θ ( n log b a ) T(n)=\Theta (n^{\log_b a}) T(n)=Θ(nlogba)
- 若 f ( n ) f(n) f(n)大于 n log b a n^{\log_b a} nlogba,且是多项式地大于,即对于某个常数 ε > 0 , f ( n ) = Ω ( n log b a + ε ) \varepsilon >0,f(n)=\Omega(n^{\log_ba+\varepsilon}) ε>0,f(n)=Ω(nlogba+ε),则有 T ( n ) = Θ ( f ( n ) ) T(n)=\Theta (f(n)) T(n)=Θ(f(n))
- 若 f ( n ) f(n) f(n)与 n log b a n^{\log_b a} nlogba同阶,则 T ( n ) = Θ ( n log b a lg n ) = Θ ( f ( n ) log n ) T(n)=\Theta (n^{\log_b a}\lg n)=\Theta (f(n)\log n) T(n)=Θ(nlogbalgn)=Θ(f(n)logn)
这样一来,我们便可以简单记为这俩谁大就和谁同阶(同时指出是多项式地大\小与),它们同阶时乘上个 log n \log n logn即可。
举个例子:
求
解
:
T
(
n
)
=
9
T
(
n
3
)
+
n
a
=
9
,
b
=
3
,
f
(
n
)
=
n
,
n
l
o
g
b
a
=
n
2
故
f
(
n
)
=
n
=
O
(
n
2
−
1
)
,
ε
=
1
则
有
T
(
n
)
=
Θ
(
n
2
)
求解:T(n)=9T(\frac{n}{3})+n \\ a=9,b=3,f(n)=n,n^{log_ba}=n^2\\ 故f(n)=n=O(n^{2-1}),\varepsilon=1\\ 则有T(n)=\Theta(n^2)
求解:T(n)=9T(3n)+na=9,b=3,f(n)=n,nlogba=n2故f(n)=n=O(n2−1),ε=1则有T(n)=Θ(n2)
总结一下:
Master定理求解递归函数复杂度
- 判断函数类型是否符合Master定理条件
- 写出 a , b , f ( n ) , n log b a a,b,f(n),n^{\log_ba} a,b,f(n),nlogba,比较 f ( n ) , n log b a f(n),n^{\log_ba} f(n),nlogba阶数的大小
- 若不同阶,需同时指出 ε \varepsilon ε(这一点很重要,因为并不是满足条件的所有式子都使用,若不能指出 ε \varepsilon ε,即并不是多项式地大小与,则定理不适用);若同阶,直接写答案
可以看到,使用Master定理极大地简化了运算。但同时,Master定理的局限性较大,一方面是对于递归函数形式的限制,另一方面必须是多项式地大于小于,非多项式大小与的也不适用。
目前不断有学者对Master定理进行拓展,以扩大它的适用范围,但因其较为复杂,本文给出的形式已经满足绝大部分需求,感兴趣的读者可以自行查阅相关文献了解。
4. 先猜后证
顾名思义,首先猜测答案应该是多少,然后适用数学归纳法进行证明。
举个例子:
求
解
:
T
(
n
)
=
2
T
(
n
2
+
17
)
+
n
求解:T(n)=2T(\frac{n}{2}+17)+n
求解:T(n)=2T(2n+17)+n
这个题我们在前面已经求解过,但还请读者暂时忘记答案。
由于 n 2 \frac{n}{2} 2n与 n 2 + 17 \frac{n}{2}+17 2n+17阶数相同,在 n n n充分大时近似相等,所以我们有理由猜测,当 n n n充分大时, T ( n 2 ) ≈ T ( n 2 + 17 ) T(\frac{n}{2})\approx T(\frac{n}{2}+17) T(2n)≈T(2n+17),故 T ( n ) = 2 T ( n 2 ) + n T(n)=2T(\frac{n}{2})+n T(n)=2T(2n)+n,易知 T ( n ) = Θ ( n log n ) T(n)=\Theta(n\log n) T(n)=Θ(nlogn),接下来再用数学归纳法进行证明。
这种方法我个人不是很推荐使用,缺点很明显:如果猜的稍微有偏差,则可能造成解不出来;可能猜对了,但数学归纳法证明不出来。总的来说就是适用于数学能力较强的人,我个人还是更建议前三种方法。
但是,我们不能抛弃这种方法,因为在某些极端情况下,猜测答案反而是最优选择,可以通过先猜大范围,然后不断压缩上界,提高下界的方法来达到”逼近“正确答案的目的。
二、总结
本文介绍了4种递归函数的求解方法,在解题的过程中,我们应该考虑以下顺序:Master定理 > 变量代换 > 迭代求解 > 先猜后证
。
同时,对于常见的递归形式,应该记住其复杂度,如 T ( n ) = 2 T ( n 2 ) + c n ⇒ Θ ( n log n ) T(n)=2T(\frac{n}{2} )+cn \Rightarrow \Theta (n\log n) T(n)=2T(2n)+cn⇒Θ(nlogn)等。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)