递归算法的复杂度
文字和代码来源:《数据结构与算法python语言描述》裘宗燕
推导过程为原创,应该有不够严谨之处,欢迎指出
递归算法通常具有如下的算法模式
def recur(n):
if n == 0:
return g(...)
somework
for i in range(a):
x = recur(n/b)
somework
somework
也就是说,n值为0时直接得到结果,否则将原问题归结为a个规模为n/b的子问题,其中a和b是由具体问题决定的两个常量。另外,在本层递归中还需要一些工作,上面描述里用somework表示,其时间复杂度可能与n有关,设为O(nk)O(n^{k})O(nk)。这个k也应该是常量,k=0表示这部分工作与n无关。
得到递归方程如下:
T(n)=O(nk)+a×T(n/b)=O(nk)+a×(O(n/b)k+a×T(n/b))=...=O(nk)+a×O(n/b)k+a2×O(n/b2)k+...+a(logbn)−1×O((n/b(logbn)−1)k)+alogbn×T(1)
T(n) = O(n^{k})+a×T(n/b)=O(n^{k})+a×(O(n/b)^{k}+a×T(n/b))=...
=O(n^{k})+a×O(n/b)^{k}+a^{2}×O(n/b^{2})^{k}+...+a^{(log_bn) - 1}×O((n/b^{(log_bn) - 1})^{k})+a^{log_bn}×T(1)
T(n)=O(nk)+a×T(n/b)=O(nk)+a×(O(n/b)k+a×T(n/b))=...=O(nk)+a×O(n/b)k+a2×O(n/b2)k+...+a(logbn)−1×O((n/b(logbn)−1)k)+alogbn×T(1)
这里面T(1)=O(1),alogbn=alogan/logab=nlogabT(1)=O(1),a^{log_bn}=a^{log_an/log_ab}=n^{log_ab}T(1)=O(1),alogbn=alogan/logab=nlogab,注意到a,b,k都是常数
所以有
T(n)=O(nk)+a×O(n/b)k+a2×O(n/b2)k+...+a(logbn)−1×O(bk)+O(nlogab)
T(n) = O(n^{k})+a×O(n/b)^{k}+a^{2}×O(n/b^{2})^{k}+...+a^{(log_bn) - 1}×O(b^{k})+O(n^{log_ab})
T(n)=O(nk)+a×O(n/b)k+a2×O(n/b2)k+...+a(logbn)−1×O(bk)+O(nlogab)
根据加法原则
当a>bk,即k<logba时a>b^{k},即k<log_ba时a>bk,即k<logba时
a>bk,T(n)=O(nlogba)
a>b^{k},T(n)=O(n^{log_ba})
a>bk,T(n)=O(nlogba)
当a=bk,即k=logba时a=b^{k},即k=log_ba时a=bk,即k=logba时
总共有(logbn+1)个O(nk)(log_bn+1)个O(n^{k})(logbn+1)个O(nk),忽略常数造成的影响
a=bk,T(n)=O(nklog2n)
a=b^{k},T(n)=O(n^{k}log_2n)
a=bk,T(n)=O(nklog2n)
当a<bk,即k>logba时a<b^{k},即k>log_ba时a<bk,即k>logba时
a<bk,T(n)=O(nk)
a<b^{k},T(n)=O(n^{k})
a<bk,T(n)=O(nk)