zoukankan      html  css  js  c++  java
  • 求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现

    使用动态规划求最大子数字和:
    s[i]表示data[i~n-1]以元素i开始的最大子数组和,a[i]表示data[i~n-1]中的最大子数组和 ;
    s[i]=max(s[i+1]+data[i], data[i]);
    a[i]=max(a[i+1], s[i]); 
    
    由于数组s,a递推的时候,都只用到数组的前一个变量,所以可以用滚动数组节省空间。 

     

    扩展问题:

     1) 如果数组首尾相连,即允许找到一组数字(A[i],···,A[n-1], A[0],···, A[j]),请使其和最大,怎么办?(书中答案错误,可以使用旋转数组的方法,时间复杂度n2,本文参考别人的想法,实现的算法复杂度为n)


     2) 如果题目要求返回最大子数组的位置,算法应该如何改变?还能保持O(N)的复杂度么?

     

    具体实现及思路如下:

     

      1 #include <cstdio>
      2 
      3 /*
      4 使用动态规划求最大子数字和:
      5 s[i]表示data[i~n-1]以元素i开始的最大子数组和,a[i]表示data[i~n-1]中的最大子数组和 ;
      6 s[i]=max(s[i+1]+data[i], data[i]);
      7 a[i]=max(a[i+1], s[i]); 
      8 
      9 由于数组s,a递推的时候,都只用到数组的前一个变量,所以可以用滚动数组节省空间。 
     10 */
     11 int maxSum(int data[], int n)
     12 {
     13     int s = data[n-1];
     14     int a = data[n-1];
     15     for(int i = n-2; i>=0; i--)
     16     {
     17         if(s<0)
     18             s=0;
     19         s+=data[i];
     20         if(s > a)
     21             a = s;
     22     } 
     23     return a;
     24 } 
     25 
     26 /*
     27 如果要求返回最大子数组和的位置,如何处理?
     28 使用curEnd记录当前最大字数组和的结束位置,
     29 当s(以元素i开始的最大子数组和) 小于零时,更新curEnd字数组末端标记,
     30 当a(当前的最大子数组和)发生变化时,更新最大字数组的标记Start,End 
     31 */ 
     32 int maxSum2(int data[], int n,int &start, int &end)
     33 {
     34     int s = data[n-1];
     35     int a = data[n-1];
     36     int curEnd = n-1;
     37     
     38     start = end = n-1;
     39     for(int i = n-2; i>=0; i--)
     40     {
     41         if(s<0)
     42         {
     43             s=0;
     44             curEnd = i;
     45         }        
     46         s+=data[i];
     47         if(s > a)
     48         {
     49             a = s;
     50             start = i;
     51             end = curEnd;
     52         }
     53             
     54     } 
     55     return a;
     56 } 
     57 
     58 /*
     59 如果数组arr[0],…,arr[n-1]首尾相邻,也就是允许找到一段数字arr[i],…,arr[n-1],arr[0],…,a[j],使其和最大,该如何?
     60 编程之美的答案的思路有问题,详见: http://www.ahathinking.com/archives/120.html
     61 参考该文算法,可知在允许数组跨界(首尾相邻)时,最大子数组的和为下面的最大值
     62 Maxsum={ 原问题的最大子数组和;数组所有元素总值-最小子数组和 }
     63 */ 
     64 int maxSum3(int data[], int n)
     65 {
     66     int maxs = data[n-1];
     67     int maxa = data[n-1];
     68     int sumAll = data[n-1];
     69     
     70     int mins = data[n-1];
     71     int mina = data[n-1];
     72     
     73     for(int i = n-2; i>=0; i--)
     74     {
     75         sumAll+=data[i];
     76         if(maxs<0)
     77             maxs=0;
     78         maxs+=data[i];
     79         if(maxs > maxa)
     80             maxa = maxs;
     81         
     82         if(mins>0)
     83             mins=0;
     84         mins+=data[i];
     85         if(mins < mina)
     86             mina = mins;
     87     } 
     88     int maxa2 = sumAll-mina;
     89     return maxa>maxa2?maxa:maxa2;
     90 } 
     91 
     92 
     93 int main()
     94 {
     95     /*
     96     int d[]={
     97         -4,-5,-6,-1,-5,-9
     98     };*/
     99     int d[]={
    100         8,-10,60,3,-1,-6
    101     };
    102     int s,e;
    103     int res = maxSum3(d,6);
    104     printf("%d
    ",res);
    105 }
  • 相关阅读:
    hdu1213
    [转]图论题集
    树剖题集
    【Python学习之旅】---线程的调用以及join方法
    【Python学习之旅】---自定制property
    【Python学习之旅】---描述符+装饰器应用
    【Python学习之旅】---类的装饰器
    【Python学习之旅】---描述符的应用
    【Python学习之旅】---上下文管理协议
    筱玛的迷阵探险(折半搜索+01字典树)
  • 原文地址:https://www.cnblogs.com/bigbigtree/p/3952494.html
Copyright © 2011-2022 走看看