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 ...
随机推荐
- 为什么java构造函数的构造器只能在第一行写this() 或者super() ?
最近在看内部类, 但是被“为什么匿名内部类或者局部内部类使用方法的局部变量时, 局部变量一定得是final类型”困扰着, 在网上查找资料的时候, 发现我对类初始化完全不了解, 之前的认识都是错误! 所 ...
- [办公自动化]企业网IE多版本引发的网页无法访问
今天同事的某个网页无法打开,但是在我的计算机上该网站确实又能打开. 去看了一下,他的其他网站都正常.确认网络本身没有问题. 最后,看了一下IE版本,IE11. 只好尝试一下兼容性视图的设置. 设置了一 ...
- TCP Operational Overview and the TCP Finite State Machine (FSM) http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF.htm
http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF.htm http://tcpipgu ...
- spring boot 使用过滤器
//启动类添加注解@ServletComponentScan package com.baiwang.invoice.utils; import java.io.IOException; import ...
- Machine Learning Note - Note 1
I am working on the Andrew Ng's course on Machine Learing. I have a question on the week2 session. I ...
- 从0开始学习Hadoop(2)安装JDK以及设置SSH
安装JDK 使用ppa/源方式安装 1.添加ppa sudo add-apt-repository ppa:webupd8team/java sudo apt-get update 2.安装oracl ...
- ExtJS Form
form表单中多选框和复选框 Ext.require([ 'Ext.form.*', 'Ext.layout.container.Column', 'Ext.window.MessageBox', ' ...
- CodeForces 723B Text Document Analysis (水题模拟)
题意:给定一行字符串,让你统计在括号外最长的单词和在括号内的单词数. 析:直接模拟,注意一下在左右括号的时候有没有单词.碰到下划线或者括号表示单词结束了. 代码如下: #pragma comment( ...
- jQuery入坑指南
前言 Ajax官方文档 爱jQuery jQuery插件库 jQuery中文api input 赋值和取值 记录一下: 在写一个input赋值,二话不说就直接利用了$('#xx').val()来进行取 ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...