方法一:暴力破解。(O(n^3))
#include <iostream>
int MaxSubseqSum1(int A[],int n){
int ThisSum, MaxSum=0;
for(int i=0;i<n;i++)
for(int j=i;j<n;j++){
ThisSum=0;
for(int k=i;k<=j;k++)
ThisSum+=A[k];
if(MaxSum<ThisSum) MaxSum=ThisSum;
}
return MaxSum;
};
int main(){
int a[7]={1,2,3,4,5,6,7};
int n=7;
std::cout<<MaxSubseqSum1(a, n);
return 1;
}
方法二:优化为(O(n^2))
#include <iostream>
int MaxSubseqSum1(int A[],int n){
int ThisSum, MaxSum=0;
for(int i=0;i<n;i++)
{
ThisSum=0;
for(int j=i;j<n;j++){
ThisSum=ThisSum+A[j];
if(MaxSum<ThisSum) MaxSum=ThisSum;
}
}
return MaxSum;
};
int main(){
int a[7]={1,2,3,4,5,6,7};
int n=7;
std::cout<<MaxSubseqSum1(a, n);
return 1;
方法三:优化为(O(nlogn)) 分治
#include <iostream>
int Max3(int a,int b,int c){
return a>b?(a>c?a:c):(b>c?b:c);
}
int MaxSubseqSum1(int A[],int left,int right){
if (left == right) { //分治毕竟是递归,递归的起点是要写的
if(A[left] > 0)
return A[left];
else
return 0;
}
int mid=(left+right)/2;
int LeftSum=MaxSubseqSum1(A, left,mid);//这里要注意,不要把left写成0哦
int RightSum=MaxSubseqSum1(A, mid+1,right);
int LeftPart=0;
int MaxLeftPart=0;
for(int i=mid;i>=left;i--){//这里的更新要注意,左边依次地去加,如果产生的sum比原来大,更新这个sum
LeftPart+=A[i];
if(LeftPart>MaxLeftPart)
MaxLeftPart=LeftPart;
}
int RightPart=0;
int MaxRightPart=0;
for(int i=mid+1;i<=right;i++){
RightPart+=A[i];
if(RightPart>MaxRightPart)
MaxRightPart=RightPart;
}
int MidSum=MaxLeftPart+MaxRightPart;
return Max3(LeftSum, RightSum, MidSum);
};
int main(){
int a[5]={-6,7,4,-3,1};
int n=5;
std::cout<<MaxSubseqSum1(a, 0,n-1);
return 0;
}
算法四,优化为(O(n)):在线算法
依次选取每个元素作为起点,向右取一段序列求和。不断更新过程中获得的最大的sum,如果sum变为负数,则更换下一个元素。其主要的观察就是,如果一个序列的第一个位置为负数,那么这个序列一定不是最大和序列(必可以把该首元素去掉)
#include <iostream>
int MaxSubseqSum1(int A[],int N){
int thisSum=0,MaxSum=0;
for(int i=0;i<N;i++){
thisSum+=A[i];
if(thisSum>MaxSum) MaxSum=thisSum;
else if(thisSum<0) thisSum=0;//这一句是画龙点睛之笔哦。thisSum本身如果超过了maxsum就更新maxsum
}
return MaxSum;
};
int main(){
int a[5]={-6,7,4,-3,1};
int n=5;
std::cout<<MaxSubseqSum1(a,n);
return 0;
}