最大子列和
2016-01-24 10:21
531 查看
一、题目描述
http://www.patest.cn/contests/mooc-ds2015spring/01-%E5%A4%8D%E6%9D%82%E5%BA%A61
给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
输入格式:
输入第1行给出正整数 K (<= 100000);第2行给出K个整数,其间以空格分隔。
输出格式:
在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20
二、思路解析
假设输入为-1,2,4,-6
提供了两种方法来解决最大自序列和的问题,func1是O(n^2)算法,func2是O(n)的算法。
func1中是用“组对数数”的办法,固定起点,依次向后加,即:[-1, -1+2, -1+2+4, -1+2+4-6], [2,2+4,2+4-6],[4-6],[6].....两层循环,所以是O(n^2)
func2中是考虑实际情况的算法。本算法是最大子序列求和问题,所有如果目前的自序列值thisValue已经是负的,则再往下加的话,多整体的结果起减小的作用。所以如果thisValue<0时,就抛弃目前起点开始的自序列,跳到下一个。这样只需要将数组遍历一遍,即可得到结果。
func3中是对01-复杂度2的解法,多了一个要求,即输出最大自序列中起止对应的数。
三、代码
[cpp] view plain copy
#include <iostream>
#include <stdlib.h>
using namespace std;
const int ARRAYSIZE = 100000;
int RESULT[3] = { 0 };
int func1(int N, int *data);
int func2(int N, int *data);
void func3(int N, int *data);
int main()
{
int N = 0;
int inputData[ARRAYSIZE] = { 0 };
int result = 0;
int start = 0;
int end = 0;
//input the num of seq.
cin >> N;
//input each number in the seq.
for (int i = 0; i < N; i++)
{
cin >> inputData[i];
}
//compute the sum.
func3(N, inputData);
//output the result
cout << RESULT[0] << " " << RESULT[1] << " " <<RESULT[2] << endl;
system("pause");
return 0;
}
int func1(int N, int *data)
{
// 遍历出所有可能结果,保存最大值。复杂度为O(n^2)
int thisValue = 0;
int maxValue = 0;
for (int start = 0; start < N; start++)
{
thisValue = data[start];
for (int end = start + 1; end < N; end++)
{
// 从一个起点开始,挨个相加后面所有可能的自序列和。
thisValue += data[end];
if (thisValue > maxValue)
{
maxValue = thisValue;
}
}
}
// 根据题目maxValue>0?选择返回值。
if (maxValue > 0)
{
return maxValue;
}
else
{
return 0;
}
}
int func2(int N, int *data)
{
/* 只遍历一次,在遍历的过程中算出最大。复杂度为O(n)思路如下:
* 1.从头开始遍历输入数据,挨个相加。thisValue表示目前子列的和,不断去更新maxValue
* 2.在遍历过程中,以thisValue为判别条件。因为要求和的最大值,所以如果当前thisValue小于0,则舍弃此子列,thisValue重新归零。
* 3.注意!不是说要舍弃为负数的数据,因为不知负数后面是什么。所以要以thisValue为条件。当第一个输入为负时,thisValue += data[0],也是负,自然舍弃。
*/
int thisValue = 0;
int maxValue = 0;
for (int i = 0; i < N; i++)
{
// 定义thisValue计算方法:挨个相加
thisValue += data[i];
// 相加为负,对和最大无贡献,所以舍弃,即使thisValue为0
if (thisValue < 0)
{
thisValue = 0;
}
// 当前子列和大于已有的最大,更新最大子列和
if (thisValue > maxValue)
{
maxValue = thisValue;
}
}
// 根据题目要求返回相应数值。>0返回最大子列值,<0返回0.
if (maxValue > 0)
{
return maxValue;
}
else
{
return 0;
}
}
void func3(int N, int *data)
{
/* 也是最大子列和问题,但输出有变化。首先要输出最大子列和,其次要输出是最大子列和相对应子列的起止元素。
思路:用func2中的O(n)算法,加一个计数器
*/
int thisValue = 0;
int maxValue = 0;
int start = 0;
int count = 0;
int end = 0;
for (int i = 0; i < N; i++)
{
thisValue += data[i];
if (thisValue <= 0)
{
count = 0;
thisValue = 0;
}
else
{
count += 1;
if (thisValue > maxValue)
{
maxValue = thisValue;
end = i;
start = i - count + 1;
}
}
// cout << "i:" << i << " start:" << start << " thisValue:" << thisValue << " end" << end << endl;
}
if (maxValue > 0)
{
RESULT[0] = maxValue;
RESULT[1] = data[start];
RESULT[2] = data[end];
}
else
{
RESULT[0] = 0;
RESULT[1] = data[0];
RESULT[2] = data[N - 1];
}
}
http://www.patest.cn/contests/mooc-ds2015spring/01-%E5%A4%8D%E6%9D%82%E5%BA%A61
给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
输入格式:
输入第1行给出正整数 K (<= 100000);第2行给出K个整数,其间以空格分隔。
输出格式:
在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20
二、思路解析
假设输入为-1,2,4,-6
提供了两种方法来解决最大自序列和的问题,func1是O(n^2)算法,func2是O(n)的算法。
func1中是用“组对数数”的办法,固定起点,依次向后加,即:[-1, -1+2, -1+2+4, -1+2+4-6], [2,2+4,2+4-6],[4-6],[6].....两层循环,所以是O(n^2)
func2中是考虑实际情况的算法。本算法是最大子序列求和问题,所有如果目前的自序列值thisValue已经是负的,则再往下加的话,多整体的结果起减小的作用。所以如果thisValue<0时,就抛弃目前起点开始的自序列,跳到下一个。这样只需要将数组遍历一遍,即可得到结果。
func3中是对01-复杂度2的解法,多了一个要求,即输出最大自序列中起止对应的数。
三、代码
[cpp] view plain copy
#include <iostream>
#include <stdlib.h>
using namespace std;
const int ARRAYSIZE = 100000;
int RESULT[3] = { 0 };
int func1(int N, int *data);
int func2(int N, int *data);
void func3(int N, int *data);
int main()
{
int N = 0;
int inputData[ARRAYSIZE] = { 0 };
int result = 0;
int start = 0;
int end = 0;
//input the num of seq.
cin >> N;
//input each number in the seq.
for (int i = 0; i < N; i++)
{
cin >> inputData[i];
}
//compute the sum.
func3(N, inputData);
//output the result
cout << RESULT[0] << " " << RESULT[1] << " " <<RESULT[2] << endl;
system("pause");
return 0;
}
int func1(int N, int *data)
{
// 遍历出所有可能结果,保存最大值。复杂度为O(n^2)
int thisValue = 0;
int maxValue = 0;
for (int start = 0; start < N; start++)
{
thisValue = data[start];
for (int end = start + 1; end < N; end++)
{
// 从一个起点开始,挨个相加后面所有可能的自序列和。
thisValue += data[end];
if (thisValue > maxValue)
{
maxValue = thisValue;
}
}
}
// 根据题目maxValue>0?选择返回值。
if (maxValue > 0)
{
return maxValue;
}
else
{
return 0;
}
}
int func2(int N, int *data)
{
/* 只遍历一次,在遍历的过程中算出最大。复杂度为O(n)思路如下:
* 1.从头开始遍历输入数据,挨个相加。thisValue表示目前子列的和,不断去更新maxValue
* 2.在遍历过程中,以thisValue为判别条件。因为要求和的最大值,所以如果当前thisValue小于0,则舍弃此子列,thisValue重新归零。
* 3.注意!不是说要舍弃为负数的数据,因为不知负数后面是什么。所以要以thisValue为条件。当第一个输入为负时,thisValue += data[0],也是负,自然舍弃。
*/
int thisValue = 0;
int maxValue = 0;
for (int i = 0; i < N; i++)
{
// 定义thisValue计算方法:挨个相加
thisValue += data[i];
// 相加为负,对和最大无贡献,所以舍弃,即使thisValue为0
if (thisValue < 0)
{
thisValue = 0;
}
// 当前子列和大于已有的最大,更新最大子列和
if (thisValue > maxValue)
{
maxValue = thisValue;
}
}
// 根据题目要求返回相应数值。>0返回最大子列值,<0返回0.
if (maxValue > 0)
{
return maxValue;
}
else
{
return 0;
}
}
void func3(int N, int *data)
{
/* 也是最大子列和问题,但输出有变化。首先要输出最大子列和,其次要输出是最大子列和相对应子列的起止元素。
思路:用func2中的O(n)算法,加一个计数器
*/
int thisValue = 0;
int maxValue = 0;
int start = 0;
int count = 0;
int end = 0;
for (int i = 0; i < N; i++)
{
thisValue += data[i];
if (thisValue <= 0)
{
count = 0;
thisValue = 0;
}
else
{
count += 1;
if (thisValue > maxValue)
{
maxValue = thisValue;
end = i;
start = i - count + 1;
}
}
// cout << "i:" << i << " start:" << start << " thisValue:" << thisValue << " end" << end << endl;
}
if (maxValue > 0)
{
RESULT[0] = maxValue;
RESULT[1] = data[start];
RESULT[2] = data[end];
}
else
{
RESULT[0] = 0;
RESULT[1] = data[0];
RESULT[2] = data[N - 1];
}
}
相关文章推荐
- 快速排序笔记
- MAC COCOA call command 调用终端控制台程序
- 在JDK源码中搜索设计模式的例子
- android之本地文件读取
- 手动备份升级WordPress
- 判断任意两台计算机的IP地址是否属于同一子网络的两种地址转换方法
- 【Groovy手札】Groovy的List
- POJ 2485(最小生成树)
- python ftplib模块编写简单的ftp服务
- 无偏估计与自由度
- java基础学习笔记
- Springmvc(5)之多部件表单、json交互和拦截器
- 分享js document.all的用法
- Java SimpleDateFormat parse 遭遇unparsable date异常
- 求方差时为什么要除以N—1,而不是除以N!【通俗理解-非数学专业】
- APUE_内存管理
- rspec 单元测试问题
- spark 命令行环境 python
- 企业项目化管理【一】:项目管理软件选型指南
- 详解PHP对象的串行化与反串行化