PAT甲级 1007 Maximum Subsequence Sum (25分) O(n)的时间复杂度

[PAT练习官网]

题目

在这里插入图片描述

解析

题目的大意就是给定一个序列,找出和最大的子序列,输出最大子序列的和,还有该子序列的起始元素和最后元素。
做这个题目是根据浙大在mooc的数据结构课程,求最大子序列的启发,采用__在线处理__可以降低时间复杂度至O(n)

代码

#include <stdio.h>

int main()
{
    int k, a[10001];
    scanf("%d", &k);
    int start = 0, end1 = k-1, sum=0, maxsum=0, temp1=0, temp2=0;//temp1和temp2暂存起始和结束位置
    for(int i=0; i<k; i++){
        scanf("%d", &a[i]);
    }
    for(int i=0; i<k; i++){
        if(sum >= 0){
            sum += a[i];
            temp2 = i;   //累加则结束位置更新
        }
        else {
            sum = a[i];  //sum小于0时前面的序列就没用了
            temp1 = temp2 = i;  //更新初始和结束位置
        }
        if(sum > maxsum || sum == 0 && end1 == k-1){
            maxsum = sum;
            start = temp1;
            end1 = temp2;
        }
    }
    printf("%d %d %d", maxsum, a[start], a[end1]);
}

注意事项,就是需要先暂时记录下来子序列的起始和终止位置,而不是更新最终的start和end,这是因为在一些情况下可能有多个相同的和相同的子序列,直接更新的话会发生错误

我踩过的一些坑

最初几次提交都是部分正确,后来找到原因是一些数据的初值设定有问题,初始的start和end必须是0和k-1,这是因为在特殊情况下(如整个数列全为正),就会导致一些问题。
还有一些小细节就是在赋值k-1时,一定要在scanf("%d", &k);后面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值