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

  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. LoadRunner系列实例之— 01录制cas登陆脚本

    关于CAS 的概念,见链接 需要增加4个关联函数,初次加载页面时取cookie和it1,输入账号密码点击登录时,取ticketGrantingTicketId和it2 实际上前后台完成两次交互, // ...

  2. swagger 如何在UI界面加入Authentication token值

    接口 2.access_token 值: 3  输入值:bearer+空格+值

  3. java8--异常处理(java疯狂讲义3复习笔记)

    try,catch,finally,throw,throws java将异常分为两种,Checked异常和Runtime异常. IndexOutOfBoundsException NumberForm ...

  4. C控制台密码输入:输入一个字符显示一个星号

    要在c控制台中输入一个字符显示一个星号, 则不能用"stdio.h'提供的库函数,因为它们都是带回显的,比如getchar() getchar()用来接收输入的字符串,输入一个字符就回显一个 ...

  5. 常用的Sublime Text插件及安装方法

    Package Control 功能:安装包管理 简介:sublime插件控制台,提供添加.删除.禁用.查找插件等功能 使用:https://sublime.wbond.net/installatio ...

  6. 【idea】idea快捷键

    Alt+回车 导入包,自动修正 alt+shift+↑  向上sout输出 psvm主函数 fori for Ctrl+N   查找类Ctrl+Shift+N 查找文件Ctrl+Alt+L  格式化代 ...

  7. hihocoder 第二十五周 spfa 最短路

    其实hihocoder里的题目目前大都是模板题啊-.- 这周的是SPFA,暑假的时候有看过SPFA,不过一直用的都是Dijkstra,感觉spfa要更加简洁一点~~,今天找了一份之前一直都看不太懂所以 ...

  8. 如何用Mac远程桌面连接windows

    打开mac,连接网络,找到系统中自带的“远程桌面连接”软件,截图如下

  9. BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流

    BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流 Description Dicing 是一个两人玩的游戏,这个游戏在Byteotia非常流行. 甚至人们专门成立了这个游戏的一 ...

  10. .NETFramework:MemoryStream

    ylbtech-.NETFramework:MemoryStream 1.返回顶部 1. #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, ...