最大连续和

问题描述:有一串数字,可正可负也可为0,连续两个或多个数字组成了一个子
序列,每个子序列都有一个和,求出所有子序列中和最大的一个。
例如输入的数组为3 6 -7 -1 4 3 -2 -5 10 -3,则和最大的子序列为3 6 -7 -1
4 3 -2 -5 10,最大和为11
 
分析: 这个问题容易想到的方法是计算出任意两点之间的序列和,取出它们中的最大值,
时间复杂度为O(n^2)
 
程序员编程艺术上提到一种二分的方法,将序列分成左右两个部分,分别计算出
左右两个部分的连续最长子序列,再求出端点分别在左右两边的连续最长子序列,
它们三个中的最大值就是整个序列上的最长连续子序列,时间复杂度是O(nlogn)
 
#include <stdio.h>
#define M 100
 
int a[M];
 
int max_sum(int left,int right)
{
    int leftmax,rightmax;      
    int leftside,rightside;    
    int leftsidemax, rightsidemax;
 
    if(left==right)
 
        return a[left]>0?a[left]:0;
    leftside=leftsidemax=0;
    rightside=rightsidemax=0;
 
    int middle=(left+right)/2;
    leftmax=max_sum(left,middle);
    rightmax=max_sum(middle+1,right);
 
   
    for(int i=middle;i>=left;i--)
    {
        leftside+=a[i];
        if(leftside>leftsidemax)
            leftsidemax=leftside;
    }
   
    for(int i=middle+1;i<=right;i++)
    {
        rightside+=a[i];
        if(rightside>rightsidemax)
            rightsidemax=rightside;
    }
    int maxside=leftmax>rightmax?leftmax:rightmax;
    int middleside=leftsidemax+rightsidemax;
    int max=maxside>middleside?maxside:middleside;
    return max;
}
 
int main()
{
    freopen("in","r",stdin);
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    int max = max_sum(0, n-1);
    printf("%d\n", max);
}
 
 
将数字存放在数组中,下标从0到n-1,假如已经求出以i为末尾的最大连续子序
列之和为sum[i],则如果要求以i+1为结尾的最大连续子序列的和sum[i+1],有
sum[i+1]=sum[i]>0 ? sum[i]+a[i+1] : a[i+1];找出它们中的最大值
 
int a[M];
int sum[M];
 
int max_sum(int left, int right)
{
    int max=0;            #考虑全是负数的情况改为max=a[left]
    sum[left]=a[left];
    for(int i=left+1;i<=right;i++)
    {
        sum[i]=sum[i-1]>0?sum[i-1]+a[i]:a[i];
        if(sum[i]>max)
            max=sum[i];
    }
    return max;
}
原文地址:https://www.cnblogs.com/qianye/p/2786366.html