PAT甲级-1007 Maximum Subsequence Sum

题目

题目大意

给定一组整数序列,求该序列中连续子序列的最大和,如果有多个子序列,取i和j较小的,输出值以及ij对应的值。

思路

刚开始把整个序列累加,用双指针,求右指针-左指针的最大值。但是第1个测试点过不去,24分。后来参考别人的代码,还有一种方法是动态规划。不用累加,直接看当前和temp是否大于0,如果小于0,说明在整个序列中起副作用,可以直接舍去;如果大于0,看是否大于sum,如果大于sum就更新sum值以及左右指针的索引。

代码1

测试点1不能过

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    int k;
    cin >> k;
    vector<int> v(k + 1);
    int flag = 0;  // 是否全为负数
    int flag2 = 0;  // 是否存在正数
    v[0] = 0;
    for (int i = 1; i <= k; i++){
        cin >> v[i];
        if (v[i] >= 0) flag = 1;
        if (v[i] > 0) flag2 = 1;
        v[i] += v[i - 1];
    }

    int maxn = 0, q = v[1], h = v[k] - v[k - 1];  // 初始化
    for (int i = 0, j = i + 1; j <= k;){
        if (v[j] >= v[j - 1]){
            j++;
            if (maxn < v[j - 1] - v[i]){
                maxn = v[j - 1] - v[i];
                q = v[i + 1] - v[i];
                h = v[j - 1] - v[j - 2];
            }
        }else{
            if (maxn < v[j - 1] - v[i]){
                maxn = v[j - 1] - v[i];
                q = v[i + 1] - v[i];
                h = v[j - 1] - v[j - 2];
            }
            i = j;
            j = i + 1;
        }
    }

    if (flag == 1 && flag2 == 0){    // 只有负数和0(测试点5)
        cout << "0 0 0" << endl;
    }else if (flag == 0){
        cout << "0 " << v[1] << " " << v[k] - v[k - 1] << endl;
    }else{
        cout << maxn << " " << q << " " << h << endl;
    }

    return 0;
}

代码2

可以通过

#include <iostream>
#include <vector>
using namespace std;

int main(){
    int k;
    cin >> k;
    vector<int> v(k);
    int sum = -1, l = 0, r = k - 1, temp = 0, t = 0;
    for (int i = 0; i < k; i++){
        cin >> v[i];
        temp += v[i];
        if (temp < 0){
            temp = 0;
            t = i + 1;
        }else if (temp > sum){
            sum = temp;
            l = t;
            r = i;
        }
    }
    if (sum < 0) sum = 0;
    cout << sum << " " << v[l] << " " << v[r] << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值