题目
Problem Description
给定n(1<=n<=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
Sample Input
6
-2 11 -4 13 -5 -2
Sample Output
20
1.直接暴力法
把所有连续子列和全部求出来找最大值,i为子列左端,j为子列右端,注意每一个新的子列要把sum=0;
复杂度 O(N^3);
int f(int a[],int n)
{
int i,j,k,sum=0,max=0;
for(i=0; i<n; i++)
{
for(j=i; j<n; j++)
{
sum=0;
for(k=i; k<=j; k++)
{
sum+=a[k];
if(sum>max) max=sum;
}
}
}
return max;
}
2.分治递归法
递归左边,中间,后边分别找最大值;
中间:从中间向两边连续求;
int f(int l,int r,int a[])
{
int sum=0,s=0,s1=0,s2=0,i;
int max1,max2;
if(l==r)
{
if(a[l]>=0) sum=a[l];
else sum=0;
}
else
{
int mid=(r+l)/2;
for(i=mid;i>=l;i--)
{
s=s+a[i];
s1=max(s,s1);
}
s=0;
for(i=mid+1;i<=r;i++)
{
s=s+a[i];
s2=max(s,s2);
}
sum=s1+s2;
max1=f(l,mid,a);
max2=f(mid+1,r,a);
sum=max(max1,sum);
sum=max(sum,max2);
}
return sum;
}
3.动态规划法
int main()
{
int n,i,a[100000],max=0,sum=0;
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
for(i=0; i<n; i++)
{
sum+=a[i];
if(sum>max) max=sum;
else if(sum<0) sum=0;
}
if(max<0) printf("0\n");
else printf("%d\n",max);
return 0;
}