[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)。
[AlgorithmClass01-1]最大连续子序列和_第1张图片

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;
}

你可能感兴趣的:(笔记)