本文解决最大子序列和问题,有两个题目组成,第二个题目比第一个要求多一些(其实就是要求输出子序列首尾元素)。

  01-复杂度1 最大子列和问题   (20分)

  给定KK个整数组成的序列{ N1​​, N2​​, ..., NK​​ },“连续子列”被定义为{ N​i​​, 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 最大子序列和的进击之路的更多相关文章

  1. PAT Maximum Subsequence Sum[最大子序列和,简单dp]

    1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...

  2. 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 01-复杂度2 Maximum Subsequence Sum (25分)

    01-复杂度2 Maximum Subsequence Sum   (25分) Given a sequence of K integers { N​1​​,N​2​​, ..., N​K​​ }. ...

  3. PAT1007:Maximum Subsequence Sum

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  4. 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 ...

  5. 1007 Maximum Subsequence Sum (PAT(Advance))

    1007 Maximum Subsequence Sum (25 分)   Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A ...

  6. python编写PAT 1007 Maximum Subsequence Sum(暴力 分治法 动态规划)

    python编写PAT甲级 1007 Maximum Subsequence Sum wenzongxiao1996 2019.4.3 题目 Given a sequence of K integer ...

  7. 1007 Maximum Subsequence Sum (25 分)

    1007 Maximum Subsequence Sum (25 分)   Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A ...

  8. PAT Advanced 1007 Maximum Subsequence Sum

    题目 1007 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1, N2, ..., N**K }. A contin ...

  9. Algorithm for Maximum Subsequence Sum z

    MSS(Array[],N)//Where N is the number of elements in array { sum=; //current sum max-sum=;//Maximum ...

随机推荐

  1. python 2.*和3.*的变化

    1.urllib2是python自带的模块,在python3.x中被改为urllib.request,如 <span style="font-size:12px;">u ...

  2. Codeforces Little Dima and Equation 数学题解

    B. Little Dima and Equation time limit per test 1 second memory limit per test 256 megabytes input s ...

  3. netstat --numeric-ports -a -t -p 排查hadoop主从节点是否建立通信

    tcp  通信 [root@hadoop2 logs]# netstat --numeric-ports -a -tActive Internet connections (servers and e ...

  4. Statement 与 PreparedStatement 区别

    Statement由方法createStatement()创建,该对象用于发送简单的SQL语句 PreparedStatement由方法prepareStatement()创建,该对象用于发送带有一个 ...

  5. Android图片载入缓存框架Glide

    Glide开源框架是Google推荐的图片载入和缓框架,其在Github上的开源地址是:https://github.com/bumptech/glide 当然一个Google推荐的框架肯定就是Vol ...

  6. Android Studio运行app时提示Error: Please select Android SDK

    最近开启了一个android项目,点“Run”键运行app,并报错Error:Please select Android SDK: 选择 File -> Project Structure 调整 ...

  7. 关于树论【LCA树上倍增算法】

    补了一发LCA,表示这东西表面上好像简单,但是细节真挺多. 我学的是树上倍增,倍增思想很有趣~~(爸爸的爸爸叫奶奶.偶不,爷爷)有一个跟st表非常类似的东西,f[i][j]表示j的第2^i的祖先,就是 ...

  8. YTU 1012: A MST Problem

    1012: A MST Problem 时间限制: 1 Sec  内存限制: 32 MB 提交: 7  解决: 4 题目描述 It is just a mining spanning tree ( 最 ...

  9. javascript 二级联动

    <html> <head> <title></title> <meta http-equiv="Content-Type" c ...

  10. C语言-1.结构体,2.枚举,3.typedef,4.预处理指令的概念,5.条件编译

    1. 结构体数组 定义:由若干个相同类型的结构体变量组成的有序的集合. 定义格式: 1) 定义结构体的同时定义结构体数组 struct Car{ int lunzi; int speed; }cars ...