分治
int max(int a,int b,int c)
{
if(a>b)
{
if(a>c)
return a;
else
return c;
}
else
{
if(b>c)
return b;
else
return c;
}
}
将数列分为两部分,最终的最大子列和要么是左半部分的最大子列和,要么是右边的最大子列和,或者是从中间那个数开始左边扫码,再往右边扫描,得到的两边最大的相加。
int maxsum(int a[],int n)
{
int left,right,leftsum=0,rightsum=0,sum=0;
//如果数据中只有一个数,它就是最大子列和,就它一个
if(n==1)
return a[0];
//通过递归求出左边的最大子列和
left=maxsum(a,n/2);
//通过递归求出右边的最大子列和
right=maxsum(a+n/2,n-n/2);
//从中间外左边扫码
for(int i=n/2-1;i>=0;i--)
{
sum+=a[i];
if(sum>leftsum)
leftsum=sum;
}
sum=0;
//从中间往右边扫码
for(int i=n/2;i<n;i++)
{
sum+=a[i];
if(sum>rightsum)
rightsum=sum;
}
//返回三者最大的
return max(left,right,(leftsum+rightsum));
}
可读性更高一点的
/*
*以分治的思想求最大子列和问题
*/
/*
*
* 将数列从中间分开
* 最大子列和可能有三种:
* 1、左边的部分的最大子列和
* 2、右边部分的最大子列和
* 3、跨越中间两边的一个最大子列和
*
*/
//创建一个比较三个数大小的函数
int max(int a,int b ,int c)
{
if(a>b)
{
if(a>c)
return a;
else
return c;
}
else
{
if(b>c)
return b;
else
return c;
}
}
//求子列和函数
int apart(int a[],int left,int right)
{
//递归边界
if(left==right)
{
return max(a[left],0);
}
int mid=(left+right)/2; //分界线
//左边的子列和
int left_sum=apart(a,left,mid);
//右边的子列和
int right_sum=apart(a,mid+1,right);
//求中间部分的子列和
int sum=0,max_left_sum=0,max_right_sum=0;
for(int i=mid;i>=left;i--)
{
sum+=a[i];
max_left_sum=max(max_left_sum,sum);
}
sum=0;
for(int i=mid+1;i<right+1;i++)
{
sum+=a[i];
max_right_sum=max(max_right_sum,sum);
}
//将三者大的返回到主函数
return max(left_sum,right_sum,(max_left_sum+max_right_sum));
}
在线处理方式
从左往右依次相加,如果出现负数,直接抛弃重新开始加,最后去中间产生的最大值
int maxsum(int a[i],int n)
{
int maxflag=0,sum=0;
for(int i=0;i<n;i++)
{
sum+=a[i];
if(sum>0)
maxflag=max(maxflag,sum);
else
sum=0;
}
cout<<maxflag;
}