开篇前言:为什么写这篇文章?笔者目前在学习各种各样的算法,在这个过程中,频繁地碰到到递归思想和分治思想,惊讶于这两种的思想的伟大与奇妙的同时,经常要面对的一个问题就是,对于一个给定的递归算法或者用分治思想缩小问题规模的算法,如何求解这个算法的时间复杂度呢?在google过很多的博文后,感觉这些博文总结的方法,有很好优秀的地方,但是都不够全面,有感于此,笔者决定总结各家之长,作此博文,总结各种方法于此,有不足之处,欢迎各位批评指证!

  在算法的分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化成为一个递归方程的求解。而对递归方程的求解,方法多种多样,不一而足。本文主要介绍目前主流的方法:代入法,迭代法,公式法,母函数法,差分方程法。


  【代入法】代入法首先要对这个问题的时间复杂度做出预测,然后将预测带入原来的递归方程,如果没有出现矛盾,则是可能的解,最后用数学归纳法证明。

  【举   例】我们有如下的递归问题:T(n)=4T(n/2)+O(n),我们首先预测时间复杂度为O(n2),不妨设T(n)=kn2(其中k为常数),将该结果带入方程中可得:左=kn2,右=4k(n/2)2+O(n)=kn2+O(n),由于n2的阶高于n的阶,因而左右两边是相等的,接下来用数学归纳法进行验证即可。


  【迭代法】迭代法就是迭代的展开方程的右边,直到没有可以迭代的项为止,这时通过对右边的和进行估算来估计方程的解。比较适用于分治问题的求解,为方便讨论起见,给出其递归方程的一般形式:

  【举   例】下面我们以一个简单的例子来说明:T(n)=2T(n/2)+n2,迭代过程如下:

  容易知道,直到n/2^(i+1)=1时,递归过程结束,这时我们计算如下:

  到这里我们知道该算法的时间复杂度为O(n2),上面的计算中,我们可以直接使用无穷等比数列的公式,不用考虑项数i的约束,实际上这两种方法计算的结果是完全等价的,有兴趣的同学可以自行验证。


  【公式法】这个方法针对形如:T(n) = aT(n/b) + f(n)的递归方程。这种递归方程是分治法的时间复杂性所满足的递归关系,即一个规模为n的问题被分成规模均为n/b的a个子问题,递归地求解这a个子问题,然后通过对这a个子问题的解的综合,得到原问题的解。这种方法是对于分治问题最好的解法,我们先给出如下的公式:

  公式记忆:我们实际上是比较n^logba和f(n)的阶,如果他们不等,那么T(n)取他们中的较大者,如果他们的阶相等,那么我们就将他们的任意一个乘以logn就可以了。按照这个公式,我们可以计算【迭代法】中提到的例子:O(f(n))=O(n2),容易计算另外一个的阶是O(n),他们不等,所以取较大的阶O(n2)。太简单了,不是吗?

  需要注意:上面的公式并不包含所有的情况,比如第一种和第二种情况之间并不包含下面这种情况:f(n)是小于前者,但是并不是多项式的小于前者。同样后两种的情况也并不包含所有的情况。为了好理解与运用的情况下,笔者将公式表述成如上的情况,但是并不是很严谨,关于该公式的严密讨论,请看这里。但是公式的不包含的情况,我们很少很少碰到,上面的公式适用范围很广泛的。

  特别地,对于我们经常碰到的,当f(n)=0时,我们有:


  【母函数法】母函数是用于对应于一个无穷序列的幂级数。这里我们解决的递归问题是形如:T(n)=c1T(n-1)+c2T(n-2)+c3T(n-3)+...+ckT(n-k)+f(n)。为说明问题简便起见,我们选择斐波那契数列的时间复杂度作为例子进行讨论。

  【举  例】斐波那契数列递归公式:T(n)=T(n-1)+T(n-2)。这里我们假设F(n)为第n项的运算量。则容易得到:F(n)=F(n-1)+F(n-2),其中F(1)=F(2)=1.我们构造如下的母函数:G(x)=F(1)x+F(2)x2+F(3)x3+......,我们可以推导如下:

  上面的方法计算相对来说是比较简单的,关键在于对于母函数的理解,刚开始的时候可能不是很好理解,对于母函数可以参考这里和维基百科这里。


  【差分方程法】可以将某些递归方程看成差分方程,通过解差分方程的方法来解递归方程,然后对解作出渐近阶估计。这里我们只考虑最长常见的递归形式,形如:T(n)=c1T(n-1)+c2T(n-2)+c3T(n-3)+...+ckT(n-k)+f(n),其中c1,c2,...ck为常数且不等于0;我们对该方程的求解如下:

  对应上面的齐次方程的特征方程为:

  如果解得t=r是该特征方程的m重根,则这m个解的形式为:{rn     n*rn      n2rn   ...    nm-1rn},其余的关于复数解的形式和普通的线性方程组的形式类似,不再赘述。接下来,我们要求解该方程的对应非齐次方程组的通解,这里我们针对该方程的特殊形式,不加证明地给出如下的通解形式:

  则和线性代数中的解一样,原方程的解等于齐次方程组的通解+特解,即:

  最后由初始条件确定a(i)的值即可。

  为了帮助理解,我们举两个例子看看,就明白是怎么回事了。

  【举 例1】递归方程如下:

(1)写出对应齐次方程的特征方程:

得到基础解系为:{t1n,  t2n}

(2)计算特解,对于本题,直接观察得特解为:-8

(3)得到原方程解的形式为:T(n)=a0t1n+a1t2n-8

(4)代入n=0,n=1的情况,得到a0,a1,最后可得:

  可以看到该方程形式和上面讨论过的斐波那契数列只差一个常数8,因而两者的时间复杂度是相同的。有兴趣的同学可以按照这个方法再次计算斐波那契数列的时间复杂度验证一下。

  【举  例2】递归方程如下:

(1)计算对应齐次方程的基础解析:

特征方程为:C(t)=t^2-4t-4=0,得到一个2重根t=2.因而其基础解为:{2n      n*2n}

(2)由于f(n)=n*2n,对应上面表格的最后一种情况,得到特解形式为:T(n)=n2(p0+p1n)2n代入原递归方程可得:p0=1/2,p1=1/6

(3)原方程解的形式为:T(n)=a0*2n+a1*n*2n+n2(1/2+n/6)2n,代入T(0),T(1)得:a0=a1=0

(4)综上:T(n)=n2(1/2+n/6)2n

因而时间复杂度为:O(n32n)


References:

[1]青青的专栏:http://blog.csdn.net/metasearch/article/details/4428865

[2]心灵深处博客:http://blog.csdn.net/metasearch/article/details/4428865

[3]wikipedia中文:母函数

[4]母函数的性质和应用:http://www.doc88.com/p-39037791334.html

[5]关于递归算法时间复杂度分析的讨论:http://wenku.baidu.com/view/719b053331126edb6f1a1091.html

[6][置顶]递归方程组解的渐进阶的求法——差分方程法:http://blog.csdn.net/explore_knight/article/details/1788046

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)网络转载请注明出处http://www.cnblogs.com/python27/

递归树求递归算法时间复杂度相关推荐

  1. 如何用递归树求快速排序时间复杂度

    其实也就是点看算法导论的心得,感觉算法导论写的有点不详细的补充 快速排序 我的理解就是利用分治法 ,递归排序最后合并的排序,因为快速排序的最坏时间复杂度比较低所以快速被叫做快速排序如图 对于求快速排序 ...

  2. 用递归树求解递归算法时间复杂度

    文章内容.图片均来自极客时间. 递归代码复杂度分析起来比较麻烦.一般来说有两种分析方法:递推公式和递归树. 1 递推公式法 归并排序的递推公式是: merge_sort(p-r) = merge(me ...

  3. 递归树——分析递归算法的时间复杂度

    递归树 递归的思想就是,将大问题分解为小问题来求解,然后再将小问题分解为小小问题. 这样一层一层地分解,直到问题的数据规模被分解得足够小,不用继续递归分解为止. 如果我们把这个一层一层的分解过程画成图 ...

  4. 求递归算法时间复杂度:递归树

    引用自:http://www.cnblogs.com/wu8685/archive/2010/12/21/1912347.html 递归算法时间复杂度的计算方程式一个递归方程: 在引入递归树之前可以考 ...

  5. 递归树求解递归算法的时间复杂度

    递归算法时间复杂度的计算方程式一个递归方程: 在引入递归树之前可以考虑一个例子: T(n) = 2T(n/2) + n2 迭代2次可以得: T(n) = n2 + 2(2T(n/4) + (n/2)  ...

  6. 遍历递归树求递推数列通项

    考虑K阶变系数线性递推方程: 现给定初值a1,a2,-,ak和n>k,要求编程打印an,an-1,-,ak+1的值 该问题用常规的迭代法非常容易解决,现在要考虑的是用遍历递归调用树的方法求解.n ...

  7. 斐波那契数列——递归与非递归算法时间复杂度分析

  8. 算法:递归(借助递归树来求解分析递归算法的时间复杂度)

    递归代码的时间复杂度分析起来非常麻烦,今天我们尝试来借助递归树分析递归算法的时间复杂度. 1. 递归树与时间复杂度分析 递归的思想就是将大问题一层一层地分解为小问题来求解,如果我们把这个分解过程画成图 ...

  9. 27 | 递归树:如何借助树来求解递归算法的时间复杂度?

    目的 借助递归树来分析递归算法的时间复杂度 递归树 递归的思想就是将大问题分解为小问题来求解,然后再将小问题分解为小小问题.这样一层一层地分解,直到问题的数据规模被分解得足够小,不用继续递归分解为止. ...

最新文章

  1. 人类偏好的“可塑性”,从博弈说起
  2. python中列表的sort方法_python中列表的sort方法使用详解
  3. iis php重定向循环,iis和apache及PHP页面设置301重定向跳转方法
  4. 安装 ZendServer-CE 可能遇到的问题
  5. android 编译系统make文件
  6. bug宝典linux篇 LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory(转)
  7. 【Udacity笔记】What is Machine Learning?
  8. 电子阅读器行业市场研究分析及未来趋势预测分析
  9. codesmith oracle 64,CodeSmith OracleModel写法
  10. VBA自动创建数据透视表
  11. mysql root不能登录密码怎么办_mysql 忘记root密码,重置密码,及重置密码后权限问题不能登录的解决方案...
  12. (四.2)计算机组成原理笔记——存储器(静态RAM和动态RAM的区别,动态RAM的刷新, ROM……)
  13. 从顶级会议Interspeech 2019看语音领域大家都在弄个啥嘞
  14. 百度小程序怎么添加到主屏幕将百度小程序放到手机桌面?
  15. 给body设置背景图片,整个图片完整的充满屏幕
  16. DELL戴尔笔记本关闭触摸板触控板WIN10
  17. 【硬件设计】AD 生成 Gerber 文件
  18. postMan传递枚举值
  19. android之broadcastreceiver 耳机按键,Android BroadcastReceiver 实时监听耳机拔出事件
  20. 困扰的Byte、bit 、和16进制之间的关系

热门文章

  1. Spark日志,及设置日志输出级别
  2. 简易的共享交通系统管理系统
  3. 【英语阅读】纽约时报 | 台湾美食为什么那么“Q”?
  4. 计算机视觉知识点之RCNN/Fast RCNN/Faster RCNN
  5. 数据库优化八大通用绝招
  6. 单点登录(Single Sign On)解决方案
  7. 计算机网络 理解流量控制与SACK机制
  8. 【Java基础】(八)方法(即C等语言中的函数)
  9. 屏幕录制和编辑神器ScreenFlow轻松上手
  10. 人脸识别考勤系统安卓APP(手把手教学-手动滑稽)