PTA 1007 Maximum Subsequence Sum

题目是浙大版数据结构视频里的原题,大意是说给出一个整数序列,让你求出和最大的连续子序列。最后输出子序列的和以及子序列的第一个数最后一个数。如果给出的序列全是负数的话,就输出0以及整个序列的第一个数和最后一个数。


这道题大致有两种做法,一种是暴力枚举每一个子序列,当然毫无疑问会超时,还有一种是在线处理。我的在线处理做法是:

  • 先定义一个last表示最大子序列的最后一个数,定义一个maxSum表示目前为止最大的子序列的和。定义一个sum用于表示当前子序列的和。

  • 从第一个数开始处理。

    • 把当前的数加到sum上,如果加上之后sum小于0,说明无论之后的数是什么,加上当前这个序列之后都会比原来的小,那么我们果断把sum清零,重新开始累计。
    • 之后判断sum是否比maxSum大,如果大的话,我们更新last和maxSum。令last等于当前数的下标,maxSum等于sum。
  • 继续往后处理,直到序列结束。

在上边那样处理完后,我们找出最大子序列和的问题是解决了。但还有一个问题,如果序列全是负数的话,sum会是0,last最后也会是0。如果序列中只有负数和0的话,最后的结果也会是sum和last都是0。这样就会导致两种情况无法区分。我的解决方法是最后从第1个数开始再找一遍,一旦找到0就可以判定是第二种情况,然后输出0 0 0,如果没有找到0,那就按第一种情况输出。

AC代码如下

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;

int arr[10001];

int main()
{
    int k;
    cin >> k;

    for (int i = 0; i < k; i++)
        scanf("%d", arr + i);

    int sum = 0, maxSum = 0, last = 0, start = 0;

    for (int i = 0; i < k; i++)
    {
        sum += arr[i];
        if (sum < 0)
            sum = 0;
        else if (sum > maxSum)
        {
            maxSum = sum;
            last = i;
        }
    }
    int t = 0;
    start = last;
    while (start >= 0)
    {
        t += arr[start];
        if (t == maxSum)
            break;
        start--;
    }

    if (maxSum == 0)
    {
        bool flag = false;
        for (int i = 0; i < k; i++)
            if (arr[i] == 0)
            {
                printf("0 %d %d", arr[i], arr[i]);
                flag = true;
                break;
            }
        if (flag == false)
            printf("0 %d %d", arr[0], arr[k - 1]);
    }
    else
    {
        printf("%d %d %d", maxSum, arr[start], arr[last]);
    }

    return 0;
}
posted @ 2020-05-03 23:14  QianXia  阅读(169)  评论(0编辑  收藏  举报