算法:最大子列和问题

本文详细介绍了求解最大子序列和问题的三种算法:暴力穷举、分而治之(动态规划)和在线处理。暴力穷举方法时间复杂度为O(N^2),分而治之通过递归实现,时间复杂度为O(NlogN),而在线处理方法以线性时间复杂度O(N)达到最优解。每种方法的代码实现和运行结果都在文中给出。
摘要由CSDN通过智能技术生成

题目来源

浙大数据结构MOOC-PTA的课后题

题目内容

分析

这个程序在课程里讲过,一共有四种方法,其中两种是同一种方法,只是进行了优化,这道题没有什么好分析的,直接写就行了。

我的程序

  1. 暴力穷举:

    #include <stdio.h>
    
    int main()
    {
        // 获取数据
        int size;
        scanf("%d", &size);
        int num[size];
        int max = 0, this = 0;
        for(int i = 0; i < size; i++)
        {
            scanf("%d", num + i);
        }
        // 穷举所有子列并找出最大和
        for(int i = 0; i < size; i++)	// 分别以每个项作为子列起点,然后计算这个起点所有子列和
        {
            this = 0;	// 每次计算完子列,都需要清空
            for(int j = i; j < size; j++)	// 计算当前所在起点的所有子列和
            {
                this += num[j];
                if(this > max)max = this;	// 当出现了更大的子列和时,将其存入max
            }
        }
        printf("%d", max);	// 打印出来
        return 0;
    }
    

    这种解法的时间复杂度为O(N2),虽然能用但是还差点意思。

  2. 分而治之:

    #include <stdio.h>
    
    int getMaxSequenceSum(int* num, int size);
    
    int main()
    {
        int size;
        scanf("%d", &size);
        int num[size];
        int max = 0;
        for(int i = 0; i < size; i++)
        {
            scanf("%d", num + i);
        }
        max = getMaxSequenceSum(num, size);
        printf("%d", max);
        return 0;
    }
    
    int getMaxSequenceSum(int* num, int size) // 分而治之,左右分并分别计算最大子列和,然后从中间向两边延申计算最大子列和,比较三者,最终得到最大子列和
    {
        if(size == 1)
        {
            return num[0]>0?num[0]:0;  // 不可再分时,最大子列和就是本身或0(小于0的情况)
        }
        int left = getMaxSequenceSum(num, size / 2);
        int right = getMaxSequenceSum(num + size / 2, size - size / 2);
        int mid_l = 0, mid_r = 0;
        int max = 0, this = 0;
        for(int i = 1; i <= size / 2; i++)
        {
            this += num[size / 2 - i];
            if(mid_l < this)mid_l = this;
        }
        this = 0;
        for(int i = 0; i < size / 2; i++)
        {
            this += num[size / 2 + i];
            if(mid_r < this)mid_r = this;
        }
        max = mid_l + mid_r > left?mid_l + mid_r:left;
        return max > right?max:right;
    }
    

    这种解法的时间复杂度为O(NlogN),已经是一种非常优秀的解法了。

  3. 在线处理:

    #include <stdio.h>
    
    int main()
    {
        // 获取数据
        int size;
        scanf("%d", &size);
        int num[size];
        int max = 0, this = 0;
        for(int i = 0; i < size; i++)
        {
            scanf("%d", num + i);
            this += num[i];
            if(this > max)max = this;
            else if(this < 0)this = 0;
        }
        printf("%d", max);	// 打印出来
        return 0;
    }
    

    在线处理的时间复杂度是O(N),时间复杂度是线性的算法,是该问题的最优解。

运行结果

下面的配图是我在MOOC中提交的图,里面代码没有优化,所以结果可能和预期有一点差别,不过整体大差没差。

1.暴力穷举

2.分而治之

3.在线处理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值