您的位置:首页 > 理论基础 > 数据结构算法

中国大学MOOC-陈越、何钦铭-数据结构 Maximum Subsequence Sum

2015-09-04 15:46 405 查看
题目描述:

Given a sequence of K integers { N​1​​ , N​2​​ , …, N​K​​ }. A continuous subsequence is defined to be { N​i​​ , N​i+1​​ , …, N​j​​ } 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

题目分析:

这道题和求最大子列问题类似,不同的是要求输出最大子列的第一位数和最后一位数.不过,这道题还多加了一些限制,例如:

①当数组全是负数时,要按0,数组第一位数,数组最后一位数输出

如 -5 -2 -5 要按0 0 0输出

②当数组不全为负数时:又分为

①没有正数时

如 -5 0 -6 要按 0 0 0输出

②有正数时:

有正数时还要考虑一些特殊情况

如: -11 0 2 5 这是输出的最大子列和的第一位数和最后一位数是0 5.③当结果不唯一时,要求输出结果对应的具有最小的第一位数有个地方要注意,当两个子列和时,并且第一位数也相等时,这是考虑的哪个元素个数少就取哪个

代码如下:

#include<iostream>
using namespace std;
void Max(int p[], int num)//求最大子列和的函数
{
int MaxSum = 0;//记录最大子列和
int Sum = 0;//记录当前的和

int Right= 0;//记录下最大子列和的最后一位数的下标
int right = 0;
/*记录下当前子列和的最后一位数的下标,
当出现最大子列和不唯一时,便于比较两者最后一位数的大小
*/

int Record_Num = 0;
int record_num = 0;
/*这两个数主要是为了记录子列从第一个数加到最后一个数,
中间间隔的数组个数
设置两个数也是为了和上面有同样的效果*/

int k = 0;//记录数组中负数的个数

for (int i = 0; i < num; i++)
{
if (p[i]<0)
{
k++;//判断数组负数个数
}

Sum += p[i];
record_num++;
//每当子列和加上了一位数组元素,record_num也对应自增

if (Sum>MaxSum)
{
MaxSum = Sum;
Record_Num = record_num;//保存当前子列和中有多少个数组元素,通过Right-Record_Num可以求出第一位数的下标
Right = i;//保存当前子列和的最后一位数的下标
}

if (Sum == MaxSum)//最大子列和不唯一时
{
right = i;//同样是为了记录当前子列和Sum的最后一位数的下标
if (p[Right - Record_Num + 1] >= p[right - record_num + 1])//先对两个子列和的第一位数的大小进行判断
{

if (p[Right - Record_Num + 1] == p[right - record_num + 1])//当两个子列和的第一位数相等时
{
if (Record_Num>record_num)//接着对两个子列和的元素个数进行判断
{
//当满足条件时进行替换
Right =right;
Record_Num = record_num;
}
}
else
{
//这里的条件是MaxSum的第一位数大于Sum的第一位数,所以需要进行替换
Right = right;
Record_Num = record_num;
}

}

}
if (Sum < 0)//当Sum小于零,就丢弃
{
Sum = 0;
record_num = 0;
}
}

if (k==num)//数组元素全是负数
{
cout << "0 ";
cout << p[0] << " " << p[num-1];
}
else
if (MaxSum == 0)//数组最大元素是0
{
cout << "0 0 0";
}else
{
//最大子列和不为0,按正常输出
cout << MaxSum << " ";

cout << p[Right - Record_Num + 1] << " ";
cout << p[Right];

}

};
int main()
{
int *p;
int num;
cin >> num;
p = new int[num];
for (int i = 0; i < num; i++)
{
cin >> p[i];
}
Max(p, num);
delete p;
p = NULL;

system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  题目分析 记录