最大子列和问题

本文介绍了四种求解最大子列和的不同算法实现及其时间复杂度分析。从O(n^3)的穷举算法逐步改进至O(n)的高效算法,并探讨了如何避免重复计算和利用递归策略。

给出一个序列,求出最大子列和。

算法一:

long MaxSum(int A[],int N)
{
    int i,j,k;
    int ThisSum=0,MaxSum=0;
    for(i=0;i<N;i++)          //i为子序列左端
    {
        for(j=i;j<N;j++)      //j为子序列右端
        {
            ThisSum0=0;
            for(k=i;k<=j;k++)    
                ThisSum += A[k];   //A[k]将子序列从i加到j
            if(ThisSum>MaxSum)
                MaxSum=ThisSum;
        }
    }
    return MaxSum;
}

这是一个穷举的算法,有三个嵌套的for循环,时间复杂度为O(n^3) 。在计算的时候有很多不必要的重复项,例如当i=0,j=3时,和的计算为:A[1]+A[2]+A[3];当i=0,j=4时,和为A[1]+A[2]+A[3]+A[4],A[1]+A[2]+A[3]的部分重合了。改进的措施是:保留之前的和,在之前和的基础上加入新的值。

算法二:

long MaxSum(int A[],int N)
{
    int i,j;
    int ThisSum=0,MaxSum=0;
    for(i=0;i<N;i++)
    {
        ThisSum=0;
        for(j=0;j<N;j++)
        {
            ThisSum +=A[j];
            if(ThisSum>MaxSum)
                MaxSum=ThisSum;
        }
    }
    return MaxSum;
}

这个算法的时间复杂度为O(n^2),这个算法在第一个for循环的开始就将ThisSum置0,之后每加上一个数的和就与MaxSum相比较,大于就将ThisSum赋给MaxSum。

算法三

long MaxSum(int A[],int left,int right)
{
    if(left==right)   //如果左右下标相等,且左下标对应的值大于0则返回
        {
        if(A[left]>0)
            return A[left];
        else
            return 0;
        }
    int center=(left+right)/2;     //求出中间下标值
    long MaxLeftSum=MaxSum(A,left,center);       //左子序列最大值
    long MaxRightSum=MaxSum(A,center+1,right);   //右子序列最大值

    long MaxLeftBoarderSum=0,LeftBoarderSum=0;
    for(i=center;i>=left;i--)        //从中间加确保左部分的最右一个值能被加上
    {
        LeftBoarderSum += A[i];
        if(LeftBoarderSum>MaxLeftBoarderSum)
            MaxLeftBoarderSum=LeftBoarderSum;
    }

    long MaxRightBoarderSum=0,RightBoarderSum=0;
    for(i=center+1;i<=right;i--)
    {
        RightBoarderSum += A[i];
        if(RightBoarderSum>MaxRightBoarderSum)
            MaxRightBoarderSum=RightBoarderSum;
    }

    return max3(MaxLeftSum,MaxRightSum,
                MaxLeftBoarderSum+MaxRightBoarderSum));  //返回三者最大值
}


long max3(long a,long b,long c)
{
    if(a<b)
        a=b;
    if(a<c)
        return c;
    else
        return a;
}

算法三的时间复杂度为:O(NlogN) ,算法三采用“分治策略”:把数组分成左右两个部分,最大子序列可能的出现的位置为左半部分,右半部分,横跨左右的中间部分。左右两个部分可以通过递归调用求出最大子序列和,中间部分需要将左半部分最大子序列和加右半部分子序列和,其中,左半部分最大子序列和要将左半部分的最右一个值求上,右半部分子序列和要将最左一个值求上。

算法四

long MaxSum(int A[],int N)
{
    long MaxSum = 0, ThisSum = 0; 
    for (int j = 0; j <N; j++) 
       { 
       ThisSum += A[j]; 
       if (ThisSum > MaxSum) 
           MaxSum = ThisSum; 
       else if (ThisSum < 0) 
           ThisSum = 0; 
       }    
}

算法四的时间复杂度为O(N) ,思想是:加起来的和如果小于-1即把子序列和归零,因为小于零的数不会让后面加进来的数变大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值