算法导论学习-子数组最大和问题

 一种算法是分治法:O(nlgn)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxsize=1000001;
 6 int a[maxsize],sum[maxsize],n,inf=(1<<30);
 7 int b[maxsize];
 8 struct solution{
 9     int lpos,rpos,sum;
10 };
11 solution find_crossing_subarray(int low,int mid,int high){
12     int left_sum=-inf,right_sum=-inf;
13     int sum=0,max_left,max_right;
14     for(int i=mid;i>=low;i--){
15         sum+=a[i];
16         if(sum>left_sum){
17             left_sum=sum;
18             max_left=i;
19         }
20     }
21     sum=0;
22     for(int i=mid+1;i<=high;i++){
23         sum+=a[i];
24         if(sum>right_sum){
25             right_sum=sum;
26             max_right=i;
27         }
28     }
29     solution a;
30     a.lpos=max_left;
31     a.rpos=max_right;
32     a.sum=left_sum+right_sum;
33     return a;
34 }
35 solution find_maximum_subarray(int low,int high){    
36     if(low==high){
37         solution s;
38         s.lpos=s.rpos=low;
39         s.sum=a[low];
40         return s;
41     }
42     int mid=(low+high)/2;
43     solution left=find_maximum_subarray(low,mid);
44     solution right=find_maximum_subarray(mid+1,high);
45     solution middle=find_crossing_subarray(low,mid,high);
46     if(left.sum>=right.sum&&left.sum>=middle.sum) return left;
47     else if(middle.sum>=left.sum&&middle.sum>=right.sum) return middle;
48     else return right;
49 }
50 int main(){
51     while(scanf("%d",&n)!=EOF&&n){
52         for(int i=1;i<=n;i++) scanf("%d",&b[i]);
53         for(int i=1;i<=n;i++){
54             a[i]=b[n-i+1];
55         }
56         solution ans=find_maximum_subarray(1,n);
57         printf("%d %d %d
",ans.sum,n-ans.rpos,n-ans.lpos);
58     }
59 }
View Code

另外一种是DP法,O(n)

maxisum-subarray problem, in fact, is try to find subarray A[i...j] of array A[1..i...j..n](1<=i<=j<=n). And the problem is meaningful only when array A has both the positve value and negative elements.

considering the size of problem:
* if n==1, the problem is quite easy. A[1] is the right answer. 
* if array A has more than one value, then we can use DP method to solve it. 

considering the procedure has already checked the A[i-1], and is going to enter the i th check. then we can assume that we have already get the maximum subarray of the A[1...i-1]. Supposing the maxisum subarray of A[1..i-1] is A[p..i-1].

Then, our procedure is going to the ith check, because we have aleady get the solution of A[1..i-1], and we will move to check A[i]. So how the relationship between sum[i-1] and sum[i]? (sum[i] stores the sum of subarray that end in A[i]). From our experience:

 

* if sum[i-1]<0, then whatever the A[i] is, the sum of subarray A[p...i-1,i] must be smaller than that of subarray A[p..i-1]. so we modify the starting indice of maxisum array from 'p' to 'i'. And at the same time, we can know that the maxisum subarray of A[1...i] is notthe A[p...i] but the A[p...i-1]. so the value of maxisum remains the same: the sum of A[p...i].
* For another circumstance, if sum[i-1]>0, we can take two situations into consideration, if A[i]>0 too, obviously, we should let sum[i]=sum[i-1]+a[i]. then for A[i]<0? in fact, we also need to plus A[i] onto sum[i-1]. as we know, in the (i-1)th calculation, acoording to the above assumption, we have already found the solution to the maxisum subarray: A[p...i-1]. So although the sum of A[p...i-1] is higher than that of A[p...i], in fact, in each iteration, we compare the value of sum[i-1] and sum[i] to the maxinum and store the maxinum. So we let the sum[i-1]+A[i] has no matter to the maxinum. 

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxsize=101;
 5 int a[maxsize],sum[maxsize],n,inf=(1<<30);
 6 void solve(){
 7     if(n==0) return;
 8     int ans=-inf;
 9     sum[1]=a[1];
10     int left=1,right=1;
11     for(int i=2;i<=n;i++){
12         if(sum[i-1]>0){
13             sum[i]=sum[i-1]+a[i];
14             right++;    
15         }
16         else{
17             sum[i]=a[i];
18             left=i;
19         }
20         if(sum[i]>ans) ans=sum[i];
21     }
22     printf("Subarray from indice %d->%d has the maximum sum: %d
",left,right,ans);        
23 }
24 int main(){
25     while(scanf("%d",&n)!=EOF){
26         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
27         solve();
28     }
29     return 0;
30 }
View Code
原文地址:https://www.cnblogs.com/fu11211129/p/4204951.html