示例:最大子列和问题

今天我们讨论的最大子列和问题出自陈越老师主编的《数据结构(第二版)》

在这篇文章中我们即将讨论最大子列和问题的解。

通过不同的算法,我们将看到算法不同时算法效率的巨大效率,从而对算法的复杂度分析有更深刻的理解。

【问题描述】

给定n个整数的序列{a1,a2,a3,···,an},求函数最大值。

【问题分析】

关于上述问题,我们可以将“子列”理解维一串连续的数字,这里想要求得的最大值即为从这串数字某一个数字个体出发加到某一个数字个体截止的所有数字之和。在求的过程中不断更新最大值,返回所有最大值中最大的那个,值得注意的是,当最后的最大值为负数时,我们要取0为最终答案。在这个过程中,我们在程序测试阶段将给定示例序列:{-2,11,-4,13,-5,-2},其最大子列为{11,-4,13},和为20。

【算法】

【算法一】

最直接的方法就是穷举所有的子列和,从中找出最大值。

与此同时,最内层的k循环涉及大量重复计算,代码效率低下。

int MaxSubseqSuml(int List[], int N)
{
    int i, j, k;
    int ThisSum, MaxSum = 0; 
    for(i=0; i<N;i++){        //i是子列左端位置
        for(j=i; j<N; j++){    //j是子列右端位置
            ThisSum=0;        //List[i]到List[j]的子列和
            for(k=i; k<=j; k++)
                ThisSum+=List[k];
            if(ThisSum>MaxSum)
                MaxSum=ThisSum;        //更新
    return MaxSum;
}

【算法二】

部分存储中间值大的穷举,当然,这仍不是最快的算法。

int MaxSubseqSum2(int List[], int N)
{
    int i, j;
    int ThisSum, MaxSum = 0; 

    for(i=0; i<N;i++){        //i是子列左端位置
        ThisSum=0;      //List[i]到List[j]的子列和
        for(j=i; j<N; j++){    //j是子列右端位置
            ThisSum+=List[j];                      
            if(ThisSum>MaxSum)
                MaxSum=ThisSum;        //更新
    return MaxSum;
}

【算法三】

分而治之,个人觉得这里可以说是来自二分查找中得到的灵感。

int Max3(int A,int B, int C)
{
    return A>B?A>C?a:C:B>C?B:C;
}

int DivideAndConquer(int List[],int left, int right)
{
    int MaxLeftSum,MaxRightSum;
    int MaxLeftBorderSum, MaxRightBorderSum;
    
    int LeftBorderSum, RightBorderSum;
    int center,i;
        
    if(left==right){
        if(List[left]>0)
            return List[left];
        else return 0;
    }
    
    center=(left+right)/2;
    MaxLeftSum=DivideAndConquer(List,left,center);
    MaxRightSum=DivideAndConquer(List,center+1,right);

    MaxLeftBorderSum=0;
    LeftBorderSum=0;
    for(i=center;i>=left;i--){
        LeftBorderSum+=List[i];
        if(LeftBorderSum>MaxLeftBorderSum)
            MaxLeftBorderSum=LeftBorderSum;

    MaxRightBBorderSum=0;
    RightBorderSum=0;
    for(i=center+1;i<=right;i++){
       RightBorderSum+=List[i];
        if(RightBorderSum>MaxRightBorderSum)
            MaxRightBorderSum=RightBorderSum;

    return Max3(MAxLeftSum,MaxRightSum,MaxLeftBOrderSum+MaxRightBorderSum);
}

int MaxSubseqSum3(int List[],int N)
{
    return DivideAndConquer(List,0,N-1);
}

        

下一篇文章将讲解在线处理算法,记得关注哦!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值