PAT甲级真题 1007 Maximum Subsequence Sum (25分) C++实现(3种方法对比:遍历法, 动态规划法,直接求解法)

题目

Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defined to be { Ni, Ni+1, …, Nj } where 1 <= i <= j <= K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.
Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.
Input Specification:
Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (<= 10000). The second line contains K numbers, separated by a space.
Output Specification:
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.
Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4

思路

首先注意坑:

  1. 题目要求输出的不是最大子段和的两个下标,而是两头的元素值!(给的示例很有迷惑性)

  2. 若全是负数,需输出整个序列头尾元素。(若求得最大子段和为负数,则可判定全是负数)

下面是三种方法求解。

遍历法

一开始用了笨方法,两重遍历所有组合,找出其中和最大的,复杂度O(n^2);

动态规划

后来尝试动态规划法。对于动态规划,一般能用一个参数表示问题边界,就不要用两个。首先考虑用C[i]表示前i个元素的最大子段和,但这样的话C[i+1]和C[i]没有明确的递推关系;故考虑用C[i]表示前i个元素中必须包含A[i]的最大子段和,这样递推关系为:
C[i+1] = A[i+1],若C[i]<=0
C[i+1] = C[i] + A[i+1],若C[i]>0
C[1] = A[1]
记录所有C[i]中最大值,及对应位置r,即可得出第一段最大子段和sum和最后位置r。

然后倒推出最前位置l,从A[r]向前累加,直到和等于sum位置即可作为j的位置。但题目中要求最小l、r,所以若l前的子段和为0,要把它们也加上。例如输入:
6
1 -1 4 -4 2 3
应输出:
5 1 3

直接求解

又学习了柳神的高端方法,基于动态规划法的思想进行简化,时间、空间复杂度都很优秀。

原文链接:https://blog.csdn.net/liuchuo/article/details/52144554

代码

遍历法,复杂度O(n^2):

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

int main(){
   
    int n;
    cin >> n;
    vector<int> v(n);
    for (int i=0; i<n; i++){
   
        cin >> v[i];
    }
    int maxSum = INT_MIN;
    int l = -1;
    int r = -1;
    for 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值