简介

分析递归的时间复杂度时通常需要用到主定理,我之前一直当作黑盒去用它,但是越来越想了解一下这个定理是如何证明的,发现证明过程只用到了等比级数与对数的相关公式,这里记录一下。

主定理

对于递归式 T(n)=aT(nb)+f(n)T(n)=aT(\cfrac{n}{b})+f(n) 的时间复杂度,主定理可以求解下面四种情况:

  1. f(n)=O(nlogbaϵ)f(n)=O(n^{\log_ba -\epsilon}) 其中 ϵ>0\epsilon >0 为常数,那么 T(n)=Θ(nlogba)T(n)=\Theta(n^{\log_ba})
  2. f(n)=Θ(nlogba)f(n)=\Theta(n^{\log_ba}),那么 T(n)=Θ(nlogbalogn)T(n)=\Theta(n^{\log_ba}\log n)
  3. f(n)=Ω(nlogba+ϵ)f(n)=\Omega(n^{\log_ba+\epsilon}),对于常数 0<c<10<c<1 和所有足够大的 nn 满足 af(nb)cf(n)af(\cfrac{n}{b})\le cf(n) 那么 T(n)=Θ(f(n))T(n)=\Theta(f(n))
  4. f(n)=Θ(nlogbalogkn)f(n)=\Theta(n^{\log_ba}\log^kn) 其中 k>0k>0 为常数,那么 T(n)=Θ(nlogbalogk+1n)T(n)=\Theta(n^{\log_ba}\log^{k+1}n)

复习一下复杂度记号:OO 代表上界,Θ\Theta 代表同级,Ω\Omega 代表下界。由于本文是复杂度相关证明,所以就严谨一点。

证明

首先画出递归树,这里贴上算法导论第四版原版 109 页中的图:

Introduction to Algorithms (Fourth Edition) P109

设根结点深度为 00,可以看出深度为 jj 的层有 aja^j 个结点,每个结点的值是 f(n/b)f(n/b) 那么此层之和为 ajf(n/bj)a^jf(n/b^j),并且最后一层有 Θ(alogbn)=Θ(nlogba)\Theta(a^{\log_bn})=\Theta(n^{\log_b a}) 个结点,所以所有结点之和就是:

Θ(nlogba)+j=0logbnajf(nbj)\Theta(n^{\log_b a})+\sum_{j=0}^{\log_b n}a^jf(\frac{n}{b^j})

g(n)=j=0logbnajf(n/bj)g(n)=\sum_{j=0}^{\log_bn}a^jf(n/b^j),下面分类讨论。

Case I

f(n)=O(nlogbaϵ)f(n)=O(n^{\log_b a-\epsilon}),代入:

g(n)=O(j=0logbnaj(nbj)logbaϵ)=O(j=0logbnaj(nlogbaϵ(bϵ)jaj))=O(nlogbaϵj=0logbn(bϵ)j)=O(nlogbaϵnϵ1bϵ1)=O(nlogba)\begin{aligned} g(n)&=O\left (\sum_{j=0}^{\log_b n} a^j\Big(\frac{n}{b^j}\Big)^{\log_ba-\epsilon}\right )\\ &=O\left( \sum_{j=0}^{\log_bn}a^j\Big(\frac{n^{\log_ba-\epsilon}(b^{\epsilon})^j}{a^j}\Big) \right)\\ &=O\left(n^{\log_ba-\epsilon }\sum_{j=0}^{\log_b n}(b^{\epsilon})^j\right)\\ &=O\left( n^{\log_ba-\epsilon}\frac{n^{\epsilon}-1}{b^{\epsilon}-1}\right)\\ &=O\left( n^{\log_ba}\right)\\ \end{aligned}

因此 T(n)=Θ(nlogba)T(n)=\Theta(n^{\log_ba}), 证毕。

Case II

f(n)=Θ(nlogba)f(n)=\Theta(n^{\log_ba}),代入:

g(n)=Θ(j=0logbnaj(nbj)logba)=Θ(j=0logbnajnlogbaaj)=Θ(nlogbalogbn)=Θ(nlogbalogn)\begin{aligned} g(n)&=\Theta\left(\sum_{j=0}^{\log_bn}a^j\Big(\frac{n}{b^j}\Big)^{\log_ba}\right)\\ &=\Theta\left(\sum_{j=0}^{\log_bn} a^j\frac{n^{\log_ba}}{a^j}\right)\\ &=\Theta\left(n^{\log_ba}\log_bn\right)\\ &=\Theta\left(n^{\log_ba}\log n\right) \end{aligned}

因此 T(n)=Θ(nlogbalogn)T(n)=\Theta(n^{\log_ba}\log n),证毕。

Case III

f(n)=Ω(nlogba+ϵ)f(n)=\Omega(n^{\log_ba+\epsilon}),对于常数 0<c<10<c<1 和所有足够大的 nn 满足 af(nb)cf(n)af(\cfrac{n}{b})\le cf(n),当 f(n)=nlogba+ϵf(n)=n^{\log_ba+\epsilon} 时,这实际上是要求:

a(nb)logba+ϵcnlogba+ϵ1bϵc\begin{aligned} a(\frac{n}{b})^{\log_ba+\epsilon}&\le cn^{\log_ba+\epsilon}\\ \frac{1}{b^{\epsilon}}&\le c \end{aligned}

也就是要求 b>1b>1,然后就可以用等比级数放缩:

g(n)=j=0logbnajf(nbj)j=0logbncjf(n)f(n)j=0cj=f(n)(11c)=O(f(n))\begin{aligned} g(n)&=\sum_{j=0}^{\log_bn}a^jf(\frac{n}{b^j})\\ &\le \sum_{j=0}^{\log_bn}c^jf(n)\\ &\le f(n)\sum_{j=0}^{\infin} c^j\\ &= f(n)(\frac{1}{1-c})\\ &=O\left(f(n)\right) \end{aligned}

根据 g(n)g(n) 的定义,g(n)=f(n)+af(n/b)+f(n)g(n)=f(n)+af(n/b)+\cdots\ge f(n),所以 g(n)=Θ(f(n))g(n)=\Theta(f(n)),因此 T(n)=Θ(f(n))T(n)=\Theta(f(n)),证毕。

Case IV

f(n)=Θ(nlogbalogkn)f(n)=\Theta(n^{\log_ba}\log^kn) 其中 k>0k>0 为常数,代入:

g(n)=Θ(j=0logbnaj(nbj)logbalogknbj)=Θ(nlogbaj=0logbn(lognjlogb)k)=Θ(nlogbalogknlogbn)=Θ(nlogbalogk+1n)\begin{aligned} g(n)&=\Theta\left(\sum_{j=0}^{\log_bn}a^j\Big(\frac{n}{b^j}\Big)^{\log_ba}\log^k\frac{n}{b^j}\right)\\ &=\Theta\left(n^{\log_ba}\sum_{j=0}^{\log_bn}(\log n-j\log b)^k\right)\\ &=\Theta\left(n^{\log_ba}\log^{k}n\log_bn\right)\\ &=\Theta\left(n^{\log_ba}\log^{k+1}n\right)\\ \end{aligned}

因此 T(n)=Θ(nlogbalogk+1n)T(n)=\Theta(n^{\log_ba}\log^{k+1}n),证毕。

总结

我的记忆方法:对于递归式 T(n)=aT(nb)+f(n)T(n)=aT(\cfrac{n}{b})+f(n),将 f(n)f(n)nlogban^{\log_ba} 比较,相等时为 Θ(nlogbalogn)\Theta(n^{\log_ba}\log n),否则当 f(n)f(n) 为多项式时,由两者较大的决定复杂度。对于 f(n)=Θ(nlogbalogkn)f(n)=\Theta(n^{\log_ba}\log^kn) 特殊记忆。

仅当 f(n)f(n)nlogban^{\log_ba} 相差 nϵn^\epsilon 阶或者 logϵn\log^{\epsilon}n 阶时,其中 ϵ\epsilon 为常数,才能用使用主定理求解复杂度,否则需要用到 Akra-Bazzi 定理,本文就不涉及了,因为我不会。