最大子列和

分治

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值