数据结构与算法分析--最大子序列和问题

最大连续子数列和一道很经典的算法问题,给定一个数列,其中可能有正数也可能有负数,我们的任务是找出其中连续的一个子数列(不允许空序列),使它们的和尽可能大。我们一起用多种方式,逐步优化解决这个问题。
例:
输入{ -2, 11, -4, 13, -5, -2 }时,答案为 20 (从A2到 A4).
算法1:

#include <stdio.h>
//N是数组长度,A是待计算的数组,放在全局区是因为可以开很大的数组
int N, A[1024];
int MaxSumsequenceSum(const int A[],int N);
int main()
{
    //输入数据
    scanf("%d", &N);
    for(int i = 1; i <= N; i++)
        scanf("%d", &A[i]);

    printf("%d\n",MaxSumsequenceSum(A,N));
    return 0;
}
int MaxSumsequenceSum(const int A[],int N)
{
    int ThisSum,MaxSum,i,j,k;
    MaxSum=0;
    for( i = 1; 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;
}

算法2:

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

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

算法3:

static int MaxSubSum(int A[], int left, int right){
    int maxLeftSum, maxRightSum;
    int maxLeftBorderSum, maxRightBorderSum;
    int leftBorderSum, rightBorderSum;

    if(left == right)
        if(A[left] > 0)
            return A[left];
        else
            return 0;

    int mid = (left + right) / 2, i;
    maxLeftSum = MaxSubSum(A, left, mid);
    maxRightSum = MaxSubSum(A, mid + 1, right);

    maxLeftBorderSum = 0, leftBorderSum = 0;
    for(i = mid; i >= left; i--){
        leftBorderSum += A[i];
        if(leftBorderSum > maxLeftBorderSum)
            maxLeftBorderSum = leftBorderSum;
    }

    maxRightBorderSum = 0, rightBorderSum = 0;
    for(i = mid + 1; i <= right; i++){
        rightBorderSum += A[i];
        if(rightBorderSum > maxRightBorderSum)
            maxRightBorderSum = rightBorderSum;
    }

    return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
}

算法4:

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

            if(ThisSum>MaxSum)
            MaxSum=ThisSum;
     else if(ThisSum<0)
           ThisSum=0;
        }
     return  MaxSum;

}

四种算法的复杂度分别为O(N^3), O(N^2) , O(NlogN) , O( N);

其中算法3采用的是”分治(divide-and-conquer)策略. 其想法是把问题分成两个大致相等的子问题,然后递归的对他们求解,这是”分”部分,”治”阶段将两个子问题的解合并到一起并可能在做些少量的附加工作,最后的到问题的解;

算法4的一个附带优点是:它只对数据进行一次扫描,一旦A[i]被读入并处理,它就不再被记忆。因此,如果数组在磁盘上,它就可以被顺序读入,在主存中不必存储数组的任何部分。不仅如此,在任意时刻,算法都能对它已经读出子序列问题的正确答案(其他算法不具有这个特性), 具有这种特性的算法叫做联机算法( online algorithm),仅需要常量空间并以线性时间运行的联机算法几乎是完美的算法.

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37999723/article/details/76850078
个人分类: 数据结构与算法
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

数据结构与算法分析--最大子序列和问题

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭