[AlgorithmClass01-1]最大连续子序列和

问题:给定一个数组A[0,…,n],求A的连续子数组,使得数组和最大。

1,暴力法

穷举尝试所有可能,时间复杂度O(n^3)

int MaxSubsequenceSum(const int A[],int N)
{
    int ThisSum, MaxSum, i, j, k;
    MaxSum = 0;
    for ( i=0; i<N; i++ )
        for ( j=i; j<N; j++ )
        {
            ThisSum = 0;
            for ( k=i; k<=j; k++ )
                ThisSum += A[k];

            if (ThisSum > MaxSum )
                MaxSum = ThisSum;
        }
    return MaxSum;
}

最内层循环可根据如下式子做改进,去掉,可得到第二种方法。

jk=iAk=Aj+j1k=iAk

2,暴力法优化

也是穷举,时间复杂度O(n^2)。

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

3,分治法

采用分治策略,将给定序列分成前后两半,则最大子序列可能有3种情况:1,出现在前半部;2,出现在后半部;3,跨越前后半部。而第三种情况可以的最大和,可以通过求出前半部分的最大和(包含前半部分最后一个元素)以及后半部分的最大和(包含后半部分的第一个元素)而得到,然后将这两个和相加。时间复杂度O(nlogn)。
这里写图片描述

static int MaxSubSum( const int A[], int Left, int Right)
{
    int MaxLeftSum, MaxRightSum;
    int MaxLeftBorderSum, MaxRightBorderSum;
    int Center, i;

    if (Left == Right)
        if ( A[Left] > 0)
            return A[Left];
        else
            return 0;

    Center = ( Left + Right ) / 2;
    MaxLeftSum = MaxSubSum( A, Left, Center );
    MaxRightSum = MaxSubSum( A, Center + 1; Right );

    MaxLeftBorderSum = 0;
    LeftBorderSum = 0;
    for( i=Center; i>=Left; i-- )
    {
        LeftBorderSum += A[i];
        if ( LeftBorderSum > MaxLeftBorderSum )
            MaxLeftBorderSum = LeftBorderSum;
    }

    MaxRightBorderSum = 0;
    RightBorderSum = 0;
    for( i=Center; i<=Right; i++ )
    {
        RightBorderSum += A[i];
        if ( RightBorderSum > MaxRightBorderSum )
            MaxRightBorderSum = RightBorderSum;
    }

    return GetMax( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );
}

int MaxSubsequenceSum( const int A[], int N )
{
    return MaxSubSum( A, 0, N-1 );
}

4,动态规划

记S[I]为以A[i]结尾的数组中和最大的子数组,则:

S[i+1]=max(S[i]+A[i+1],A[i+1])

初始时S[0]=A[0],遍历i: 0 <= i <= n-1
时间复杂度O(n)

int MaxSubsequenceSum( const int A[], int N )
{
    int ThisSum, MaxSum, j;
    ThisSum = 0;
    MaxSum = ThisSum;

    for ( j=0; j<N; j++ )
    {
        if(ThisSum > 0)
            ThisSum += a[i];
        else
            ThisSum = a[i];
        if(MaxSum < ThisSum)
            MaxSum = ThisSum;

    }
    return MaxSum;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值