最大子数组问题

题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间负责度为O(n)。

首先想到的是求出这个整型数组所有子数组的和,长度为n的数组一共有 n(n+1)/2个子数组,要求出这些连续子数组的和最快也需要O(n^2)的时间复杂度。

可见我们只能对整个数组进行O(n)的遍历。假如输入数组为{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7},假如我们从头到尾累加其中的数,初始化和为0,第一步加上1,此时和为1,第二步加上-2,此时和为-1,第三步加上3,此时我们发现-1+3=2,最大和2反而比3一个单独的整数小,这是因为3加上了一个负数。所以:如果当前和为负数,那么就放弃前面的累加和,从数组中的下一个数再开始计数。

 

#include<iostream>
#include<stdlib.h>
using namespace std;

//求最大连续子序列和
int FindGreatestSumOfSubArray(int arry[],int len)
{
    if(arry==NULL||len<=0)
        return -1;
    int start=0,end=0;//用于存储最大子序列的起点和终点
    int p=0;//指针,用于遍历数组。
    int currSum=0;//保存当前最大和
    int greatestSum=-10000;//保存全局最大和
    for(int i=0;i<len;i++)
    {
        if(currSum<0)//如果当前最大和为负数,则舍弃前面的负数最大和,从下一个数开始计算
        {
            currSum=arry[i];
            p=i;
        }
        else
            currSum+=arry[i];//如果当前最大和不为负数则加上当前数
        if(currSum>greatestSum)//如果当前最大和大于全局最大和,则修改全局最大和
        { 
            greatestSum=currSum;
            start=p;
            end=i;
        }
    }
    cout<<"最大子序列位置:"<<start<<"->"<<end<<endl;
    return greatestSum;
}



int main()
{
    int arry[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    int len=sizeof(arry)/sizeof(int);
    //cout<<len<<endl;
    int sum= FindGreatestSumOfSubArray(arry,len);
    cout<<"最大子序列和:"<<sum<<endl;

    return 1;
}

采用分治法来求解:最大子数组出现在下列两种情况中。

1.最大子数组位于原数组的左子数组中或右子数组中,此种情况直接调用递归算法。

2.最大子数组跨越两个字数组,此时我们需要找到左子数组中以a[mid]结尾的最大子数组和右子数组中以a[mid+1]开头的最大子数组,两个之和即为所求。

#include<iostream>
#include<stdlib.h>
using namespace std;

int Max(int a,int b)  
{  
    return a>b?a:b;  
} 

int BinReMax(int a[],int l,int r)  
{  
    int center=0;  
    int mlpart=0,mrpart=0,lpart=0,rpart=0,i=0;  
    if(l==r)  
    {  
        if(a[l]>0)return a[l];  
        else return 0;  
    }  
    center=(l+r)/2;  
    for(i=center;i>=l;i--)  
    {  
        lpart+=a[i];  
        if(lpart>mlpart)
            mlpart=lpart;  
    }  
    for(i=center+1;i<=r;i++)  
    {  
        rpart+=a[i];  
        if(rpart>mrpart)
            mrpart=rpart;  
    }  
    return Max(mlpart+mrpart,Max(BinReMax(a,l,center),BinReMax(a,center+1,r)));  
}  
int main()  
{  
    int arry[]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};  
    int len=sizeof(arry)/sizeof(int);
    cout<<BinReMax(arry,0,len)<<endl;  
    return 0;
}  
点赞