分治问题中递归函数时间复杂度浅析
Preface
在各类分治 (Divide-and-Conquer) 问题中, 我们经常使用递归函数来方便地进行子问题的处理和结果的合并. 典型的例子有归并排序 (merge sort) 和离散快速傅里叶变换 (Fast Fourier Transform)。对于这种递归函数算法的时间复杂度分析我们可以使用三种方法:代入法 (The substitution method) , 递归树法 (The recursion-tree method) 和使用大名鼎鼎的主定理 (The Master Theorem) 的主定理法 (The Master Method) .
在这里, 我们使用这样的方法表示一个递归函数, 例如:T(n)=2T(⌈n2⌉)+n
代入法(The substitution method)
所谓代入法其实就是猜一个答案,然后将这个答案代入递归函数的表达式中来验证我们的猜测是正确的,其实是用到了数学归纳的方法.
_e.g._ 求T(n)=2T(⌊n2⌋)+n的时间复杂度上界(upper bound).
我们首先猜想答案是O(nlog2n), 所以我们需要证明T(n)<=cnlog2n. 不妨假设这个结论已经对所有小于n的数成立,于是代入T(⌊n2⌋)
得
T(n)=2T(⌊n2⌋)+n<=2c⌊n2⌋log2⌊n2⌋+n<=2cn2log2n2+n=cn(log2n−1)+n=cnlog2n−cn+n显然当c>=1时可以说明我们的假设是正确的
为了严格证明我们当然还需要注意两个方面:第一个是达到边界时的情况(也就是递归树的叶节点);还有一个就是归纳的起始条件,也就是说,为了归纳证明,我们需要另外证明n在小于某一个数时我们的假设是成立的。但是为了方便起见,我们可以不用处理上述因素。
我们需要猜测一个答案来开始我们的代入法, 但是很多时候我们可能并不能第一下就猜出正解,我们可以先猜一个比较松的界,然后逐步收敛得到我们想要的答案。
同时算法导论上还讲述了一个比较精巧的方法, 当我们猜测出来的答案并不足够强以证明不等式,我们可以在猜测的不等式中减去低阶项(lower-order term)后再代入。
例如算法导论中给出的例子T(n)=T(⌊n2⌋)+T(⌈n2⌉)+1
如果我们猜测T(n)<=cn,发现带入结果是T(n)<=cn+1,不足以证明我们的猜想
这时我们减去一个低阶项T(n)<=cn−d再次代入,得T(n)<=cn−2d+1, 只要d>=1,T(n)<=cn−d就成立
递归树法(The recursion-tree method)
咕
主定理法(The master method)
主定理法是为了求出下述通式的递归式的时间复杂度的
T(n)=aT(nb)+f(n)a,b均为大于等于1的常数,f(n)是一个渐进正函数(asymptotically positive function)
这里的nb既可以指上取整也可以指下取整
主定理法当然是依据下面这个主定理来的:
If f(n)=O(nlogba−ϵ) for some constant ϵ>0,then T(n)=Θ(nlogba).
If f(n)=Θ(nlogba),then T(n)=Θ(nlogbalgn).
If f(n)=Ω(nlogba+ϵ) for some constant ϵ>0, and if af(n/b)≤cf(n) for some constant c<1 and all sufficiently large n,then T(n)=Θ(f(n)).
举几个例子:
递归建堆 T(n)=T(2n/3)+1
a=1,b=32,logab=0,nlogab=1=f(n)
所以 T(n)=Θ(logn)
归并排序 T(n)=2T(n/2)+Θ(n)
a=2,b=2,nlogab=n
所以 T(n)=Θ(nlogn)
References
Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to algorithms. MIT press., http://thuvien.thanglong.edu.vn:8081/dspace/bitstream/DHTL_123456789/3760/2/introduction-to-algorithms-3rd-edition.pdf
oiertyq commented5 years ago
肯定是用递归树法啊
The above comments are provided by comment.js with the help of Github issue.
去评论