递归算法的时间复杂度分析

在算法分析中,当一个算法中包括递归调用时,其时间复杂度的分析会转化为一个递归方程求解。实际上,这个问题是数学上求解渐近阶的问题,而递归方程的形式多种多样,其求解方法也是不一而足,比較经常使用的有下面四种方法:

(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

,第二类与第三类之间也存在这样的情况,此时公式法不适用。

时间: 2024-08-01 05:18:01

递归算法的时间复杂度分析的相关文章

递归算法的时间复杂度分析 转载

在算法分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化为一个递归方程求解.实际上,这个问题是数学上求解渐近阶的问题,而递归方程的形式多种多样,其求解方法也是不一而足,比较常用的有以下四种方法: (1)代入法(Substitution Method)        代入法的基本步骤是先推测递归方程的显式解,然后用数学归纳法来验证该解是否合理.        (2)迭代法(Iteration Method)        迭代法的基本步骤是迭代地展开递归方程的右端,使之成为一个非递归的和

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

递归算法大家都不陌生,当需要重复计算相同问题时,一般可以选择递归和循环两种算法.又因为递归实现起来代码比较简洁,所以通常都会使用递归来解决上述问题.比如斐波那契数列,再比如树的前序.中序.后续遍历算法. 递归算法虽然是有代码简洁这个优点,但是其缺点显著.因为递归函数是在执行过程中调用其自身,所以会占用大量的栈上空间,并且压栈和出栈都是有时间消耗的.所以从这一点上来看,递归的效率是不如循环.除了效率之外,递归还有一个相当明显的问题:可能会导致栈溢出.当递归调用的次数过大时,很有可能会出现栈溢出的情

(转)递归树求递归算法的时间复杂度

本文转载:http://www.cnblogs.com/wu8685/archive/2010/12/21/1912347.html 递归算法时间复杂度的计算方程式一个递归方程: 在引入递归树之前可以考虑一个例子: T(n) = 2T(n/2) + n2 迭代2次可以得: T(n) = n2 + 2(2T(n/4) + (n/2) 2) 还可以继续迭代,将其完全展开可得: T(n) = n2 + 2((n/2) 2 + 2((n/22)2 + 2((n/23) 2 + 2((n/24) 2 +-

C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析

尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这个游戏:按这样的规则,剩下一个人,游戏就结束,这个人就为赢家.(读者可以试着表达,不认同,直接忽略) 抽象分析 这个人就是一个数据个体,数据结点,数据元素.上面产生的数据结构为:单方向循环的链.可以用链表实现,也可以用数组来实现. 链表到数组的迁移 人(数据元素. 数据结点.数据个体) 结点关系 (

选择排序的时间复杂度分析

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最前(最后),直到全部待排序的数据元素排完.选择排序是不稳定的排序方法. 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了.那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了.比较拗口,举个例子,序列5 8 5

合并排序算法时间复杂度分析

一.合并已排序的两个数组,依次比较两个数组元素大小,并按大小加入到暂存数组B,最后保存到A: Algorithm: MERGE(A, p, q, r) 输入:数组A[p...q]和A[q+1...r],各自按升序排列 输出:将A[p...q]和A[q+1...r]合并后的升序排序的新数组 01. s←p; t←q+1; k←p; {s, t, p 分别指向A[p...q], A[q+1...r]和暂存数组B} 02. while s≤q and t≤r 03. if A[s] ≤A[t] the

算法时间复杂度分析基础

摘要      本文论述了在算法分析领域一个重要问题--时间复杂度分析的基础内容.本文将首先明确时间复杂度的意义,而后以形式化方式论述其在数学上的定义及相关推导.从而帮助大家从本质上认清这个概念. 前言      通常,对于一个给定的算法,我们要做 两项分析.第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式.数学归纳法等.而在证明算法是正确的基础上,第二部就是分析算法的时间复杂度.算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上

算法的时间复杂度分析

在上一篇文章中对时间复杂度及其举例进行了简单描述,本篇文章将分析算法的时间复杂度和相关方法. 1.事前分析估算的方法 因事后统计方法更多的依赖于计算机的硬件.软件等环境因素,有时容易掩盖算法本身的优劣.因此人们常常采用事前分析估算的方法.本文对事后统计方法不做描述.在编写程序前,依据统计方法对算法进行估算.一个用高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素: (1). 算法采用的策略.方法:(2). 编译产生的代码质量:(3). 问题的输入规模:(4).  机器执行指令的速度.

红黑树的插入和遍历时间复杂度分析

红黑树的插入和遍历时间复杂度分析 在平常的工作中,最常用的一种数据结构恐怕是std::map了.因此对其的时间复杂度分析是有必要的,编写程序时做到心中有底. 一.理论分析 在stl中std::map和std::set都采用红黑树的方式实现.我们知道插入一个元素到红黑树的时间为log(N),其中N为当前红黑树的元素个数,因此,采用插入方式构建元素个数为N的红黑树的时间复杂度为: log(1) + log(2) + log(N-1) = log((N-1)!) = Nlog(N) 那么采用迭代器遍历