首先用分治法:
#include "stdio.h"
int MaxSum(int a[],int left,int right)
{
int i,sum=0;
if(left==right)
sum=a[left]>0?a[left]:0;
else
{
int center=(left+right)/2;
int leftsum=MaxSum(a,left,center);
int rightsum=MaxSum(a,center+1,right);
int s1=0,s2=0,lefts=0,rights=0;
for(i=center;i>=left;i--)
{
lefts+=a[i];
if(lefts>s1)
s1=lefts;
}
for(i=center+1;i<=right;i++)
{
rights+=a[i];
if(rights>s2)
s2=rights;
}
sum=s1+s2;
if(sum<leftsum) sum=leftsum;
if(sum<rightsum) sum=rightsum;
}
return sum;
}
void main()
{
int i,s=0;
int a[6];
printf("请输入6个整数:");
for(i=0;i<6;i++)
scanf("%d",&a[i]);
s=MaxSum(a,1,6);
printf("最大子段和为:%d",s);
}
然后是动态规划方法:
#include "stdio.h"
int MaxSum(int n,int a[])
{
int i,sum=0,b=0;
for(i=1;i<=n;i++)
{
if(b>0)
b+=a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
return sum;
}
void main()
{
int i,s=0;
int a[6];
printf("请输入6个整数:");
for(i=0;i<6;i++)
scanf("%d",&a[i]);
s=MaxSum(6,a);
printf("最大子段和为:%d",s);
}
#include <stdio.h>
int FindGreatestSecSum(int *a,int len)
{
int sum = 0, max = 0;
for(int i = 0; i < len; i++)
{
if(sum <= 0)
sum = a[i];
else
sum += a[i];
if(sum > max)
max = sum;
}
return max;
}
int main()
{
int a[8] = {4,-3,5,-2,-1,2,6,-2};
printf("%d/n", FindGreatestSecSum(a,sizeof(a)/sizeof(int)));
return 0;
}
#include <stdio.h>
int FindGreatestSecSum(int *a,int len)
{
int sum = 0, max = 0;
for(int i = 0; i < len; i++)
{
if(sum <= 0)
sum = a[i];
else
sum += a[i];
if(sum > max)
max = sum;
}
return max;
}
int main()
{
int a[8] = {4,-3,5,-2,-1,2,6,-2};
printf("%d/n", FindGreatestSecSum(a,sizeof(a)/sizeof(int)));
return 0;
}
为了方便大家理解,这里转载一篇别人的解法,看了这篇文章之后,我对这个问题
的理解更加清晰了,在此向作者表示感谢。
最大子段和问题的动态规划求解
1. 基本原理
设数组为a[k],1≤k≤n,最大子段和X 被定义为:
j
X = max { ∑a[k] }
1≤i≤j ≤n k=i
不妨设:
j
b[j ] = max { ∑ a[k]}
1 ≤j ≤n k=m
其中m 是可变的。注意:a[j]必须是b[j]这个最大局部受限子段和所对应子段的最右端,
好好理解此处j 和b[j]的含义是整个算法的关键!
根据b[j]和X 的定义,不难发现:
X = max b[j ]
1≤j ≤n
另一方面,根据b[j]的定义,可以看出:
当b[j-1]>0 时,无论a[j]为何值,b[j]=b[j-1]+a[j];
当b[j-1]≤0 时,无论a[j]为何值,b[j]=a[j];
所以有:
b[j ] = max { b[j -1] +a[j ],a[j ] }
1≤j ≤n
2. 具体实例
k 1 2 3 4
a[k] 3 -4 2 10
b[k] 3 -1 2 12
其中:b[1]=a[1],b[2]=b[1]+a[2],b[3]=a[3],b[4]=b[3]+a[4] ;因此,对于数组a 而言,
最大子段和为b[4],即X=12 。
3. 编程实现
略,针对数组a 进行一遍扫描即可。算法实现的时间复杂度只有O(n)。