数组的最大连续子序列

今天在网上看到的这道题目:

一个有N个元素的整型数组arr,有正有负,数组中连续一个或多个元素组成一个子数组,这个数组当然有很多子数组,求子数组之和的最大值。例如:[0,-2,3,5,-1,2]应返回9,[-9,-2,-3,-5,-3]应返回-2。

开始感觉貌似也没有那么难,就直接想循环遍历+动态规划的方法写即可。O(n2)的复杂度,感觉略大,想到上次关于最大子矩阵方法适合的O(n)的方法,感觉这个问题肯定也有这样的解法。在网上搜罗了一下,果真有各种简单的方法,仔细一看,这些方法之间还有关联性,这真的是一种思维方式的不同。

在我以前的想法中,只要能解决问题就行了,但是最近看了很多资料,觉得很多东西都不是自己开始以为的那么简单,很多东西都是需要深入研究学习的,感觉自己真的有很多不懂的地方。只想对自己说:加油,zxh。

废话不多说,代码、详细注释和思维流程都在这里:

 1 //根据动态规划方法,另外设置一个数组subSum[i][j]表示序列i-j的元素的和;
 2 //由题意知道:
 3 //subSum[i][j]=arr[j]  i==j
 4 //subSum[i][j]=subSum[i][j-1]+arr[j]  j<j
 5 //当arr[j]<0时候,subSum[i][j]<subSum[i][j-1]当前的max判断可以省略
 6 int maxSubArr(int arr[],int len){
 7     int sum=INT_MIN,i,j,end;
 8     if(len<=0) return sum;
 9     int **subSum=(int**)malloc(sizeof(int*)*len);
10     for(j=0;j<len;j++)
11     {
12         subSum[j]=(int*)malloc(sizeof(int)*len);
13     }
14 
15     for (i=1;i<len+1;i++)//不同长度
16     {
17         for(j=0;j<=len-i;j++)//不同起始下标
18         {
19             end=j+i-1;
20             if(end==j)
21                 subSum[j][end]=arr[end];
22             else
23                 subSum[j][end]=arr[end]+subSum[j][end-1];
24             if(arr[end]>0 )sum=max(sum,subSum[j][end]);
25         }
26     }
27 
28     for(j=0;j<len;j++)
29     {
30         free(subSum[j]);
31     }
32     free(subSum);
33 
34     return sum;
35 }
36 
37 //DP求解方法
38 //可以对数组中最后那一个元素进行分析,arr[len-1],最长子序列跟这个arr[len-1]的关系:
39 //arr[len-1]就是所要求的最长子序列max=arr[len-1]
40 //arr[len-1]是最长子序列的结尾,则有max=arr[len-1]+max[len-2]
41 //arr[len-1]跟最长子序列无关,即max=arr[len-2]
42 //end[i]表示以arr[i]为结尾的所有子序列中和的最大值
43 //all[i]表示从0-i中的序列中和最大的子序列的和
44 //这个只是为了表达清楚,我们其实还可以进一步优化,减少空间复杂度
45 int maxSubArr2(int arr[],int len){
46     int end[30],all[30];
47     int i=0;
48     end[i]=all[i]=arr[0];
49     for (i=1;i<len;i++)
50     {
51         end[i]=max(arr[i],end[i-1]+arr[i]);
52         all[i]=max(end[i],all[i-1]);
53     }
54     return all[i-1];
55 }
56 //maxSubArr2的优化版本
57 int maxSubArr3(int arr[],int len){
58     int end,all;
59     int i=0;
60     end=arr[0];
61     all=arr[0];
62     for (i=1;i<len;i++)
63     {
64         end=max(arr[i],end+arr[i]);
65         all=max(end,all);
66     }
67     return all;
68 }
69 //另一个改进版本
70 //71 //end=max(arr[i],end+arr[i]);
72 //all=max(end,all);
73 //这两句,我们可以看到,end是取的arr[i]和arr[i]+end的最大值,那这两个值只有在end<0的情况下才取arr[i]
74 //也就是当end<0时候就重新累加,丢弃掉原来的结果
75 //那么过程就出来了,就是一直累加,每当遇到累加和小于0的时候就从头开始
76 int maxSubArr4(int arr[],int len){
77     int sum=arr[0],maxVal=INT_MIN;
78     int i=0;
79     for (i=1;i<len;i++)
80     {
81         if (sum<0) sum=arr[i];
82         else sum+=arr[i];
83 
84         maxVal=max(sum,maxVal);
85     }
86     return maxVal;
87 }

巨人的肩膀:http://www.ahathinking.com/archives/120.html

原文地址:https://www.cnblogs.com/havePassed/p/3900103.html