题目
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
思路
首先注意坑:
-
题目要求输出的不是最大子段和的两个下标,而是两头的元素值!(给的示例很有迷惑性)
-
若全是负数,需输出整个序列头尾元素。(若求得最大子段和为负数,则可判定全是负数)
下面是三种方法求解。
遍历法
一开始用了笨方法,两重遍历所有组合,找出其中和最大的,复杂度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