zoukankan      html  css  js  c++  java
  • 最大子序列和的【分治递归】求法

    首先标明递归的四要素:

    关于(1)基准情形,是说必须有不用递归就能求解的情况。否则,递归将永远进行下去。
    可以看下这个例子:
    int badRecursion( int n )
    {
            if ( n == 0 )
                return 0;
            else 
                return badRecursion ( n/3 + 1 ) + n - 1;
    }
    你可以算一下,当计算到badRecursion(1)时,将一直计算下去。因为他没有一个终止循环的条件。

    (2)(3)很好理解,就不说了。
    (4)是说递归算法的效率性。
    可以看一下这个递归算法:
    long fib(int n)
    {
        if ( n <= 1 )
            return 1;
        else
            return fib( n - 1 ) + fib( n - 2 );
    }
    这个算法看起来是个递归,可是当把n的数值调大后会发现它的效率低的惊人。简单分析一下就可以看出,最后一行语句第一次调用 fib(n-1) 实际上同时计算了fib(n-2)。这个信息被抛弃而在最后一行语句第二次调用时又重新计算了一遍。这违反了准则(4)。这可以解释为什么不用递归计算斐波那契数了。

    下面是代码和注解 

     1 int  maxSumRec(const vector<int>&a,int left,int right)  
     2 
     3 {  
     4 
     5     int maxLeftSum,maxRightSum; //表示  
     6 
     7     int rightBorderSum = 0,leftBorderSum = 0;  
     8 
     9     int maxLeftBorderSum = 0,maxRightBorderSum = 0;  
    10 
    11     int center;  
    12 
    13     if(left == right) //解决小容量情况,当序列只有一个元素时,非负则返回唯一值,否则返回0(基准情况)  
    14 
    15     {  
    16 
    17         if(a[left]>0)  
    18 
    19         {  
    20 
    21             return a[left];  
    22 
    23         }else 
    24 
    25         {  
    26 
    27             return 0;  
    28 
    29         }  
    30 
    31     }  
    32 
    33     center = (left+right)/2;  
    34 
    35     maxLeftSum = maxSumRec(s,left,center); //每次递归返回时,该值为该子段的最终左最大子序列和  
    36 
    37     maxRightSum = maxSumRec(s,center+1,right); //每次递归返回时,该值为该子段的右最大自序列和  
    38 
    39     for(int i=center;i>=left;i--) //从中间向左扩展求子段的最大子序列和,必然包括子段的最右端数  
    40 
    41     {  
    42 
    43         leftBorderSum+=s[i];  
    44 
    45         if(leftBorderSum>maxLeftBorderSum)  
    46 
    47         {  
    48 
    49             maxLeftBorderSum = leftBorderSum; //包含左端数的最大子序列和  
    50 
    51         }  
    52 
    53     }  
    54 
    55     for(int j=center+1;j<=right;j++) //从中间向右扩展求子段的最大子序列和,必然包括子段的最左端数  
    56 
    57     {  
    58 
    59         rightBorderSum += a[j];  
    60 
    61         if(rightBorderSum > maxRightBorderSum)  
    62 
    63         {  
    64 
    65             maxRightBorderSum = rightBorderSum; //包含右端数的最大子序列和  
    66 
    67         }  
    68 
    69     }  
    70 
    71     //返回左子最大序列和,右最大子序列,及横跨中间的最大子序列和三者的最大值  
    72 
    73     return max3(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);   
    74 
    75 }   
  • 相关阅读:
    DTD与shema学习
    xml基本语法学习
    快速写出main方法和system.out.print()
    Eclipse常见快捷键
    System.out.print()与toString()
    HttpURLConnection学习
    如何查看开关机时间
    阿里云云服务器硬盘分区及挂载
    java环境搭建
    使用jstack 发现死锁
  • 原文地址:https://www.cnblogs.com/ll-10/p/5391756.html
Copyright © 2011-2022 走看看