最大子段和

来源:互联网 发布:弯矩图计算软件 编辑:程序博客网 时间:2024/05/29 18:17

问题描述:

给你搞定由n个整数(可能为负整数)组成的序列a1,a2,a3,......,an,求该序列的连续子段和的最大值。当所有整数均为负整数时定义其最大子段和为0。

问题分析:

解决该问题有多种方法,在此分别用如下方法解决:

(1)穷举搜索法。

(2)递归分治法。

(3)动态规划法。

代码如下:

穷举搜索法

public static int MaxSum()
{
int n=a.length-1;
int sum=0;
for (i=1;i<=n ; i++)
{
int thissum=0;
for (int j=i;j<=n ;j++ )
{
thissum+=a[j];
if(thissum>sum)
{
sum=thissum;
besti=i;
bestj=j
}
}
}
return sum;
}

递归分治法:

使用递归分治法的条件:原问题可以分解为与原问题性质相同的子问题(通俗讲,即原问题与子问题具有相同的求解过程,计算代码相同参数不同),从顶到底,先解决子问题,然后用子问题去解决原问题。

如果将所给的序列a[1:n]分为长度相等的2段a[1:n/2]和a[n/2+1,n],分别求出这两段的最大子段和,则a[1:n]的最大字段和有以下3种情况:

(1)a[1:n]的最大子段和与a[1:n/2]的最大字段和相同。

(2)a[1:n]的最大子段和与a[n/2+1:n]的最大字段和相同。

(3)a[1:n]的最大子段和为Eak,且1<=i<=n/2,n/2+1<=j<=n;

算法如下:

static int maxSubSum(int left,int right)
{
int sum=0;
if(left==right)sum=a[left]>0?a[left]:0;   //递归的出口,且所有整数均为负整数时定义最大子段和为0。left==right表明为其中一个元素
else
{
int center=(left+right)/2;
int leftsum=maxSubSum(left,center);
int rightsum=maxSubSum(center+1,right);
int s1=0;
int lefts=0;
for(int i=center;i>=left;i--)
{
lefts+=a[i];
if(lefts>s1)s1=lefts;
}
int s2=0;
int rights=0;
for (int i=center+1;i<=right ;i++ )
{
rights+=a[i];
if(rigths>s2)s2=rights;
}
sum=s1+s2;
if(sum<leftsum)sum=leftsum;
if(sum<rightsum)sum=rightsum;
}
return sum;
}

动态规划算法:

满足最优子性质,递归式如下:

b[j]=max{b[j-1]+a[j],a[j]},1<=j<=n,

b[j]为{a1,a2,...,aj}的最大子段和

代码如下:

public static int maxSum()
{
int n=a.length-1;
int sum=0,
   b=0;
for(int i=1;i<=n;i++)
{
if(b>0)b+=a[i];
else b=a[i];
if(b>sum)sum=b;
}
return sum;
}


0 0