Maximum Subsequence Sum 最大子序列和的进击之路
本文解决最大子序列和问题,有两个题目组成,第二个题目比第一个要求多一些(其实就是要求输出子序列首尾元素)。
01-复杂度1 最大子列和问题 (20分)
给定KK个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1 ..., Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:
- 数据1:与样例等价,测试基本正确性;
- 数据2:102个随机整数;
- 数据3:103个随机整数;
- 数据4:104个随机整数;
- 数据5:105个随机整数;
输入格式:
输入第1行给出正整数K≤100000;第2行给出K个整数,其间以空格分隔。
输出格式:
在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20
这道题解决方法的算法复杂度可以从O(N^3)、O(N^2)、O(NlogN)优化到O(N),以下是代码:
O(N^3):
1 #include <stdio.h>
2
3 /* O(N^3) Maxium Subsequence */
4
5 int main(){
6 int seq[100001];
7 int n, i, j, k;
8 int tmpsum;
9 int maxsum = 0;
10 scanf("%d", &n);
11 for(i = 0; i < n; i++){
12 scanf("%d", &seq[i]);
13 }
14 for(i = 0; i < n; i++){
15 for(j = i; j < n; j++){
16 tmpsum = 0;
17 for(k = i; k < n; k++){
18 tmpsum += seq[k];
19 if(tmpsum > maxsum )
20 maxsum = tmpsum;
21 }
22 }
23 }
24 printf("%d", maxsum);
25 return 0;
26 }
O(N^2):
1 #include <stdio.h>
2
3 /* O(N^2) Maxium Subsequence */
4
5 int main(){
6 int seq[100001];
7 int n, i, j;
8 int tmpsum;
9 int maxsum = 0;
10 scanf("%d", &n);
11 for(i = 0; i < n; i++){
12 scanf("%d", &seq[i]);
13 }
14 for(i = 0; i < n; i++){
15 tmpsum = 0;
16 for(j = i; j < n; j++){
17 tmpsum += seq[j];
18 if(tmpsum > maxsum )
19 maxsum = tmpsum;
20 }
21 }
22 printf("%d", maxsum);
23 return 0;
24 }
第三种算法采取了分治法,将序列一分为二,然后不断递归,再将左右边分别一分为二,不断切割,以(seq[left] == seq[right])为暂停标志,由此求出左子列最大和以及右子列最大和,同时,以中点为中心,分别向左右两边扫描,分别求出maxleftbodersum 和 maxrightbodersum, 之后得到跨越边界最大和 maxleftbodersum + maxrightbodersum, 最后比较 maxleftsum、 maxrightsum、maxleftbodersum + maxrightbodersum 三者取最大。可以发现,在递归中,结构是一样的,比如: 在左子列分割过程中,也不断地在重复以上过程,因此采用递归。
O(NlogN):
1 #include <stdio.h>
2 int Max3(int A, int B, int C){
3 return A > B ? A > C ? A : C : B > C ? B : C;
4 }
5 int Divide(int list[], int left, int right){
6 int MaxLeftsum, MaxRightsum;
7 int LeftBodersum, RightBodersum;
8 int MaxLeftBodersum, MaxRightBodersum;
9 int center, i;
10 if(left == right){
11 if(list[left] > 0)
12 return list[left];
13 else
14 return 0;
15 }
16 center = (left + right) / 2;
17 MaxLeftsum = Divide(list, left, center);
18 MaxRightsum = Divide(list, center + 1, right);
19 MaxLeftBodersum = 0;
20 LeftBodersum =0;
21 MaxRightBodersum = 0;
22 RightBodersum = 0;
23 for(i = center; i >= left; i--){
24 LeftBodersum += list[i];
25 if(LeftBodersum > MaxLeftBodersum)
26 MaxLeftBodersum = LeftBodersum;
27 }
28 for(i = center + 1; i <= right; i++){
29 RightBodersum += list[i];
30 if(RightBodersum > MaxRightBodersum)
31 MaxRightBodersum = RightBodersum;
32
33 }
34 return Max3(MaxLeftsum, MaxRightsum, MaxRightBodersum + MaxLeftBodersum );
35 }
36
37 int MaxSubseq( int list[], int N){
38 return Divide(list, 0, N - 1);
39 }
40 int main(){
41 int seq[100001];
42 int n;
43 int i;
44 scanf("%d", &n);
45 for(i = 0; i < n; i++ ){
46 scanf("%d", &seq[i]);
47
48 }
49 printf("%d\n", MaxSubseq(seq, n));
50
51 return 0;
52 }
O(N):
1 #include <stdio.h>
2
3 /* O(N) Maxium Subsequence */
4
5 int main(){
6 int seq[100001];
7 int n, i;
8 int tmpsum = 0;
9 int maxsum = 0;
10 scanf("%d", &n);
11 for(i = 0; i < n; i++){
12 scanf("%d", &seq[i]);
13 }
14 for(i = 0; i < n; i++){
15 tmpsum += seq[i];
16 if(tmpsum > maxsum)
17 maxsum = tmpsum;
18 else if(tmpsum < 0)
19 tmpsum = 0;
20 }
21 printf("%d", maxsum);
22 return 0;
23 }
那么接下来在PAT甲级测试的1008 Maximum Subsequence Sum (25分)中,将这个问题难度稍微加大一些,要求输出子序列最小首尾元素(因为可能出现并列和相等的子序列)。原题如下
1007. Maximum Subsequence Sum (25)
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)算法最好,用第三种算法反倒不太方便。只不过需要增加记录子序列开始的index和结束的index。
代码如下:
1 #include <stdio.h>
2 int main(){
3 int n,i;
4 int seq[100001];
5 scanf("%d", &n);
6 for(i = 0; i < n; i++){
7 scanf("%d", &seq[i]);
8 }
9 int start = 0;
10 int end = 0;
11 int tmpindex = 0;
12 int tmpsum = 0;
13 int maxsum = -1;
14 //flag is a symbol to check whether every element in seq is nonnegative
15 int flag = 0;
16
17 for(i = 0; i < n; i++){
18 if(seq[i] >= 0){
19 flag = 1;
20 }
21 tmpsum += seq[i];
22 if(tmpsum > maxsum){
23 maxsum = tmpsum;
24 end = i;
25 start = tmpindex;
26 }else if(tmpsum < 0){
27 tmpsum = 0;
28 tmpindex = i + 1;
29 }
30
31 }
32 if(flag == 0){
33 printf("0 %d %d\n", seq[0], seq[n - 1]);
34
35 }else{
36 printf("%d %d %d\n", maxsum, seq[start], seq[end] );
37 }
38
39
40 return 0;
41 }
上面代码中,关键是maxsum的初始值,一定是-1而不是0,我最初的错误就犯在这里,当初始maxsum = 0时,始终有一项AC不了,即当序列中只有一个0且其他全为负数时,当seq[i] = 0, tmp = 0时,如果maxsum是0,就进入不了第一个if判断,这是最容易疏忽的一点。
Maximum Subsequence Sum 最大子序列和的进击之路的更多相关文章
- PAT Maximum Subsequence Sum[最大子序列和,简单dp]
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 01-复杂度2 Maximum Subsequence Sum (25分)
01-复杂度2 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1,N2, ..., NK }. ...
- PAT1007:Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- PAT 甲级 1007 Maximum Subsequence Sum (25)(25 分)(0不是负数,水题)
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- 1007 Maximum Subsequence Sum (PAT(Advance))
1007 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N1, N2, ..., NK }. A ...
- python编写PAT 1007 Maximum Subsequence Sum(暴力 分治法 动态规划)
python编写PAT甲级 1007 Maximum Subsequence Sum wenzongxiao1996 2019.4.3 题目 Given a sequence of K integer ...
- 1007 Maximum Subsequence Sum (25 分)
1007 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N1, N2, ..., NK }. A ...
- PAT Advanced 1007 Maximum Subsequence Sum
题目 1007 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1, N2, ..., N**K }. A contin ...
- Algorithm for Maximum Subsequence Sum z
MSS(Array[],N)//Where N is the number of elements in array { sum=; //current sum max-sum=;//Maximum ...
随机推荐
- 对于api安全性的思考
目前的情况下api被很多地方应用,随之而来的是api的安全性问题. 我所认识到的安全性问题有以下几个方面: 1.DDoS(拒绝服务攻击),接口被恶意调用,使真实的用户无法享受到正常畅通的服务. ...
- EJB学习笔记六(EJB中的拦截器)
1.前言 听到拦截器,预计都不陌生,尤其是在Servlet规范中,充分应用了拦截器的概念.EJB3也提供了拦截器的支持,本质上是轻量级的AOP实现.拦截器能够将多个业务方法中的通用逻辑从业务方法中抽 ...
- 【扩展知识2】函数strlen()和非函数sizeof的使用
[扩展知识2]函数strlen()和非函数sizeof的使用 [扩展文件夹] strlen函数 sizeof ( 1 )函数strlen() 原型:size_tstrlen ( const char ...
- FOUNDATION OF ASYNCHRONOUS PROGRAMMING
The async and await keywords are just a compiler feature. The compiler creates code by using the Tas ...
- UVA315 Network —— 割点
题目链接:https://vjudge.net/problem/UVA-315 A Telephone Line Company (TLC) is establishing a new telepho ...
- Watir: Get document detail information in Watir.
ie.#{element}(:id,"foo").document.currentstyle.attributeAsCamelCase so ie.#{element}(:id,& ...
- 虚拟机安装hadoop
1.用VMware建立两台虚拟机(Centos6.5)系统,并设立主机名为node1与node2 2.设置虚拟机网络两台都是设置为如图: 3.修改两台虚拟机的/etc/hosts的文件为 (其中192 ...
- bzoj 3205: [Apio2013]机器人【dfs+斯坦纳树+spfa】
第一次听说斯坦纳树这种东西 先dfs预处理出来dis[i][j][k]表示格子(i,j)向k方向转移能到哪,记忆话搜索预处理,注意如果有环的话特判一下 设f[i][j][x][y]表示复合机器人i-j ...
- Tensor Operation
Main operation categories that encompass the operations of tensors. Reshaping operations Element-wis ...
- 【正睿多校联盟Day4 T4 简单的数论题】
题目名有毒 由于并没有系统地开始学习数论,所以数论题基本靠暴力. 然鹅本题的题解相当简单: emmm....我当你没说 一个简单易懂的方法是这样的: 1. 欧拉定理的推论 若正整数a,n互质,则对于任 ...