zoukankan      html  css  js  c++  java
  • 递归函数时间复杂度分析

    递归函数时间复杂度分析

     

    (1) 递归运行过程 
       样例:求N!。 
        这是一个简单的"累乘"问题,用递归算法也能解决。 
        n! = n * (n - 1)!   n > 1 
        0! = 1, 1! = 1      n = 0,1 
        因此,递归算法例如以下: 
       
    Java代码 
    fact(int n) {  
        if(n == 0 || n == 1)   
             return 1;  
            else   
                 return n * fact(n - 1);  
        }  
        以n=3为例,看运行步骤例如以下: 
        fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3) 
        ------------------------------>  ------------------------------> 
                    递归                            回溯 
      递归算法在运行中不断调用自身减少规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,開始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。 
       算法的起始模块也是终止模块。 
    (2) 递归实现机制 
        每一次递归调用,都用一个特殊的数据结构""记录当前算法的运行状态,特别地设置地址栈,用来记录当前算法的运行位置,以备回溯时正常返回。递归模块的形式參数是普通变量,每次递归调用得到的值都是不同的,他们也是由""来存储。 
    (3) 递归调用的几种形式 
        一般递归调用有以下几种形式(当中a1a2b1b2k1k2为常数)。 
       <1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...}; 
        
       <2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...}; 
        <3> 间接递归调用:  f(n) {...a1 * f((n - k1) / b1); ...}, 
                            g(n) {...a2 * f((n - k2) / b2); ...}。 
    2. 递归算法效率分析方法 
       递归算法的分析方法比較多,最经常使用的便是迭代法。 
      迭代法的基本步骤是先将递归算法简化为相应的递归方程,然后通过重复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再预计和的渐进阶。 
      <1> 例:n! 
           算法的递归方程为: T(n) = T(n - 1) + O(1); 
           迭代展开: T(n) = T(n - 1) + O(1) 
                           = T(n - 2) + O(1) + O(1) 
                           = T(n - 3) + O(1) + O(1) + O(1) 
                           = ...... 
                           = O(1) + ... + O(1) + O(1) + O(1) 
                           = n * O(1) 
                           = O(n) 
          这个样例的时间复杂性是线性的。 
    <2> 例:例如以下递归方程: 
          
          T(n) = 2T(n/2) + 2, 且如果n=2k次方。 
          T(n) = 2T(n/2) + 2 
               = 2(2T(n/2*2) + 2) + 2 
               = 4T(n/2*2) + 4 + 2 
               = 4(2T(n/2*2*2) + 2) + 4 + 2 
               = 2*2*2T(n/2*2*2) + 8 + 4 + 2 
               = ... 
               = 2(k-1)次方 * T(n/2(i-1)次方) + $(i:1~(k-1))2i次方 
               = 2(k-1)次方 + (2k次方)  - 2 
               = (3/2) * (2k次方) - 2 
               = (3/2) * n - 2 
               = O(n) 
          这个样例的时间复杂性也是线性的。 
    <3> 例:例如以下递归方程: 
          
          T(n) = 2T(n/2) + O(n), 且如果n=2k次方。 
          T(n) = 2T(n/2) + O(n) 
               = 2T(n/4) + 2O(n/2) + O(n) 
               = ... 
               = O(n) + O(n) + ... + O(n) + O(n) + O(n) 
               = k * O(n) 
               = O(k*n) 
               = O(nlog2n) //2为底 
         
          一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为: 
          O(n)          (a<c && c>1) 
          O(nlog2n)     (a=c && c>1) //2为底 
          O(nlogca)     (a>c && c>1) //n(logca)次方,以c为底 
       上面介绍的3种递归调用形式,比較经常使用的是第一种情况,另外一种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析 
    比較复杂。 以下举个另外一种形式的递归调用样例。 
      <4> 递归方程为:T(n) = T(n/3) + T(2n/3) + n 
         为了更好的理解,先画出递归过程相应的递归树: 
                                n                        --------> n 
                        n/3            2n/3              --------> n 
                  n/9       2n/9   2n/9     4n/9         --------> n 
               ......     ......  ......  .......        ...... 
                                                         -------- 
                                                         总共O(nlogn) 
         累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是: 
        
          n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1 
         设最长路径为k,则应该有: 
          
         (2/3)k次方 * n = 1 
         得到 k = log(2/3)n  // (2/3)为底 
         于是 T(n) <= (K + 1) * n = n (log(2/3)n + 1) 
         即 T(n) = O(nlogn) 
        由此样例表明,对于另外一种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。

  • 相关阅读:
    Generate Parentheses
    Length of Last Word
    Maximum Subarray
    Count and Say
    二分搜索算法
    Search Insert Position
    Implement strStr()
    Remove Element
    Remove Duplicates from Sorted Array
    Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4215481.html
Copyright © 2011-2022 走看看