请问递归算法的时间复杂度如何计算呢?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请问递归算法的时间复杂度如何计算呢?相关的知识,希望对你有一定的参考价值。

递归算法的时间复杂度在算法中,当一个算法中包含递归调用时,其时间复杂度的分析会转化为一个递归方程求解,常用以下四种方法:  

1.代入法(Substitution Method)  

代入法的基本步骤是先推测递归方程的显式解,然后用数学归纳法来验证该解是否合理。  

2.迭代法(Iteration Method)  

迭代法的基本步骤是迭代地展开递归方程的右端,使之成为一个非递归的和式,然后通过对和式的估计来达到对方程左端即方程的解的估计。  

3.套用公式法(Master Method)  

这个方法针对形如“T(n) = aT(n/b) + f(n)”的递归方程。这种递归方程是分治法的时间复杂性所满足的递归关系。

即一个规模为n的问题被分成规模均为n/b的a个子问题,递归地求解这a个子问题,然后通过对这a个子间题的解的综合,得到原问题的解。  

4.差分方程法(Difference Formula Method)  

可以将某些递归方程看成差分方程,通过解差分方程的方法来解递归方程,然后对解作出渐近阶估计。  

扩展资料:

1.递归是指对一个问题的求解,可以通过同一问题的更简单的形式的求解来表示,并通过问题的简单形式的解求出复杂形式的解,是解决一类问题的重要方法。

2.递归程序设计是程序设计中常用的一种方法,它可以解决所有有递归属性的问题,并且是行之有效的.

3.但对于递归程序运行的效率比较低,无论是时间还是空间都比非递归程序更费,若在程序中消除递归调用,则其运行时间可大为节省.

参考技术A 递归算法的时间复杂度分析 收藏
在算法分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化为一个递归方程求解。实际上,这个问题是数学上求解渐近阶的问题,而递归方程的形式多种多样,其求解方法也是不一而足,比较常用的有以下四种方法:

(1)代入法(Substitution Method)

代入法的基本步骤是先推测递归方程的显式解,然后用数学归纳法来验证该解是否合理。

(2)迭代法(Iteration Method)

迭代法的基本步骤是迭代地展开递归方程的右端,使之成为一个非递归的和式,然后通过对和式的估计来达到对方程左端即方程的解的估计。

(3)套用公式法(Master Method)

这个方法针对形如“T(n) = aT(n/b) + f(n)”的递归方程。这种递归方程是分治法的时间复杂性所满足的递归关系,即一个规模为n的问题被分成规模均为n/b的a个子问题,递归地求解这a个子问题,然后通过对这a个子间题的解的综合,得到原问题的解。

(4)差分方程法(Difference Formula Method)

可以将某些递归方程看成差分方程,通过解差分方程的方法来解递归方程,然后对解作出渐近阶估计。

下面就以上方法给出一些例子说明。

一、代入法

大整数乘法计算时间的递归方程为:T(n) = 4T(n/2) + O(n),其中T(1) = O(1),我们猜测一个解T(n) = O(n2 ),根据符号O的定义,对n>n0,有T(n) < cn2 - eO(2n)(注意,这里减去O(2n),因其是低阶项,不会影响到n足够大时的渐近性),把这个解代入递归方程,得到:

T(n) = 4T(n/2) + O(n)
≤ 4c(n/2)2 - eO(2n/2)) + O(n)
= cn2 - eO(n) + O(n)
≤ cn2

其中,c为正常数,e取1,上式符合 T(n)≤cn2 的定义,则可认为O(n2 )是T(n)的一个解,再用数学归纳法加以证明。

二、迭代法

某算法的计算时间为:T(n) = 3T(n/4) + O(n),其中T(1) = O(1),迭代两次可将右端展开为:

T(n) = 3T(n/4) + O(n)
= O(n) + 3( O(n/4) + 3T(n/42 ) )
= O(n) + 3( O(n/4) + 3( O(n/42 ) + 3T(n/43 ) ) )

从上式可以看出,这是一个递归方程,我们可以写出迭代i次后的方程:

T(n) = O(n) + 3( O(n/4) + 3( O(n/42 ) + ... + 3( n/4i + 3T(n/4i+1 ) ) ) )

当n/4i+1 =1时,T(n/4i+1 )=1,则

T(n) = n + (3/4) + (32 /42 )n + ... + (3i /4i )n + (3i+1 )T(1)
< 4n + 3i+1

而由n/4i+1 =1可知,i<log4 n,从而

3i+1 ≤ 3log4 n+1 = 3log3 n*log4 3 +1 = 3nlog4 3

代入得:

T(n) < 4n + 3nlog4 3,即T(n) = O(n)。

三、套用公式法

这个方法为估计形如:

T(n) = aT(n/b) + f(n)

其中,a≥1和b≥1,均为常数,f(n)是一个确定的正函数。在f(n)的三类情况下,我们有T(n)的渐近估计式:

1.若对于某常数ε>0,有f(n) = O(nlogb a-ε ),则T(n) = O(nlogb a )

2.若f(n) = O(nlogb a ),则T(n) = O(nlogb a *logn)

3.若f(n) = O(nlogb a+ε ),且对于某常数c>1和所有充分大的正整数n,有af(n/b)≤cf(n),则T(n)=O(f(n))。

设T(n) = 4T(n/2) + n,则a = 4,b = 2,f(n) = n,计算得出nlogb a = nlog2 4 = n2 ,而f(n) = n = O(n2-ε ),此时ε= 1,根据第1种情况,我们得到T(n) = O(n2 )。

这里涉及的三类情况,都是拿f(n)与nlogb a 作比较,而递归方程解的渐近阶由这两个函数中的较大者决定。在第一类情况下,函数nlogb a 较大,则T(n)=O(nlogb a );在第三类情况下,函数f(n)较大,则T(n)=O(f (n));在第二类情况下,两个函数一样大,则T(n)=O(nlogb a *logn),即以n的对数作为因子乘上f(n)与T(n)的同阶。

但上述三类情况并没有覆盖所有可能的f(n)。在第一类情况和第二类情况之间有一个间隙:f(n)小于但不是多项式地小于nlogb a ,第二类与第三类之间也存在这种情况,此时公式法不适用。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/metasearch/archive/2009/08/09/4428865.aspx本回答被提问者采纳
参考技术B   1、递归
  是指对一个问题的求解,可以通过同一问题的更简单的形式的求解来表示. 并通过问题的简单形式的解求出复杂形式的解. 递归是解决一类问题的重要方法. 递归程序设计是程序设计中常用的一种方法,它可以解决所有有递归属性的问题,并且是行之有效的. 但对于递归程序运行的效率比较低,无论是时间还是空间都比非递归程序更费,若在程序中消除递归调用,则其运行时间可大为节省. 以下讨论递归的时间效率分析方法,以及与非递归设计的时间效率的比较.
  2、时间复杂度的概念及其计算方法
  算法是对特定问题求解步骤的一种描述. 对于算法的优劣有其评价准则,主要在于评价算法的时间效率,算法的时间通过该算法编写的程序在计算机中运行的时间来衡量,所花费的时间与算法的规模n有必然的联系,当问题的规模越来越大时,算法所需时间量的上升趋势就是要考虑的时间度量。
  算法的时间度量是依据算法中最大语句频度(指算法中某条语句重复执行的次数)来估算的,它是问题规模n的某一个函数f(n). 算法时间度量记作:T(n)=O(f(n)) 。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的时间复杂度,简称时间复杂度[2]。
  例如下列程序段:
(1)x=x+1;(2)for(i=1;i<=n;i++) x=x+1;(3)for(j=1;j<=n;j++) for(k=1;k<=n;k++) x=x+1. 以上三个程序段中,语句x=x+1的频度分别为1,n,n2,则这三段程序的时间复杂度分别为O(1),O(n),O(n2)。
  求解过程为:先给出问题规模n的函数的表达式,然后给出其时间复杂度T(n)。
  但是在现实程序设计过程中,往往遇到的问题都是比较复杂的算法,就不能很容易地写出规模n的表达式,也比较难总结其时间复杂度. 递归函数就是属于这种情况. 下面举例说明递归函数的时间复杂度的分析方法。

算法计算时间复杂度:求递归式 f(n) = 2f(n/2) + n

当 n = 1 时,f(n) = 1; 

当 n > 1 时,f(n) = 2*f(n/2) + n ;

求f(n)的递归式

首先为什么要求递归式呢? 是因为在计算机中有些算法是使用递归方式实现,我们需要计算该递归方式的时间复杂度,来评定算法的优劣。

下面我们来求f(n)的递归式,什么是递归式呢?就是等号左边只有f(n),等号右边只有关于n的表达式。

看到f(n) = 2*f(n/2) + n 这个式子你想到了什么,是不是将f(n/2)变掉。

如何将f(n/2) 变掉呢?

可以假设 n = 2k ,那么 f(n) = f(2k) 然后假设 f(2k) = h(k),  f(n/2) = f(k) = h(k/2) 显然这么做毫无意义。

也可以假设 n = 2^k ,那么 f(n) = f(2^k) 然后假设 f(2^k) = h(k), f(n/2) = f(2^(k-1)) = h(k-1)。

那么 f(n) = 2*f(n/2) + n  =>  h(k) = 2*h(k-1) + 2^k ;

另外 n = 1 时,f(n) = 1 ,1 = 2^k  => k = 0 时 h(k) = 1 ;

 

换句话说就是

将 

当 n = 1 时,f(n) = 1; 

当 n > 1 时,f(n) = 2*f(n/2) + n ;

=>

n = 2^k ;

当 k = 0 时 h(k) = 1 ;

当 k > 0 时 h(k) = 2*h(k-1) + 2^k ;

h(1) = 2*h(0) + 2^1

h(2) = 2*h(1) + 2^2

h(3) = 2*h(2) + 2^3

 

h(3)= 2*(2*h(1) + 2^2) + 2^3

       = 2^2 * h(1) + 2^3 + 2^3

       = 2^2 * (2*h(0) + 2^1) + 2^3 + 2^3

       = 2^3 * h(0) + 2^3 + 2^3 + 2^3

       = 4 * 2^3

h(k) = 2^k * h(0) + k * (2^k)

      = (k + 1) * 2^k 

我们得到了 h(k) = (k + 1) * 2^k ,因为 n = 2^k => k = log2 n , f(n) = h(k)

f(n) = (log2 n + 1) * 2^log2 n

      = (log2 n + 1) * n

      = n * log2 n + n

于是得到了 f(n) = n * log2 n + n 。

在得到了递归式之后,时间复杂度 O(nlog2 n) 

 

延伸知识:

求等差数列的前n项和,求等比数列的前n项和

 

等差数列 A1 = 1,A2 = 2, A3 = 3 …… An = n ; 等差数列 每一项都是前一项加一个常数,这里是1

Sn = A1 + A2 + A3 + …… + An

    = 1 + 2 + 3 + …… + n

以下是等差数列的前n项和的推导过程

 Sn = 1 + 2 + 3 + …… + n

 Sn = n + (n - 1) + (n - 2) + …… + 1

Sn + Sn = (1 + n) + (2 + (n - 1)) + (3 + (n - 2)) + …… + (1 + n)

2 * Sn = n * (n + 1)

Sn = n * (n + 1)/2 

 

等比数列 A1 = 2^1,A2 = 2^2, A3 = 2^3 …… An = 2^n ; 等比数列 每一项都是前一项乘以个常数,这里是2

Sn = A1 + A2 + A3 + …… + An

     = 2^1 + 2^2 + 2^3 + …… + 2^n

 

Sn  = 2^1 + 2^2 + 2^3 + …… + 2^n

2 * Sn = 2^2 + 2^3 + …… + 2^n + 2^(n + 1)

2 * Sn - Sn = 2^(n + 1) - 2^1

Sn = (2^(n + 1) - 2^1 ) / (2 - 1)

 

以上是关于请问递归算法的时间复杂度如何计算呢?的主要内容,如果未能解决你的问题,请参考以下文章

算法计算时间复杂度:求递归式 f(n) = 2f(n/2) + n

掌握递归关系时间复杂度的定理

贪婪递归算法的时间复杂度

Python 算法的时间复杂度和空间复杂度 (实例解析)

递归算法时间复杂度分析与改善

数据结构&算法_算法基础之前传(递归时间复杂度空间复杂度二分查找)