PAT 甲级测试题目 -- 1007 Maximum Subsequence Sum

题目链接

题目描述

  给一组序列的个数 N(N < 10000)以及序列中的数,要求计算出该序列中连续子序列和值最大的子序列,输出这个最大值以及子序列的第一个元素和最后一个元素,若序列中的值均为负数,则子序列和值最大为0,输出序列的第一个元素和最后一个元素。

分析

  由于题目中给出的个数在 10000 左右,因此使用数组存储子序列不是一个好办法。
由于题目中表明是计算连续的子序列,因此可以这样推理结果:
  若有序列{ a1, a2, a3, a4, a5, a6},且 a2 至 a6 的子序列和为正数,a1 为负数,那么子序列 { a1, a2, a3, a4, a5, a6 } 一定不是该序列的最大值,因此可以舍弃元素 a1。也由此可以推出,若有子序列1,子序列2以及子序列3,且子序列1,子序列2之和为负数,子序列3之和为正数,那么子序列3的和可能为该序列的最大子序列和。由此可以推出思路:

设置最大值 maxium 为 0,用 currentAdd 变量记录当前加和的值,
若 currentAdd 大于 maxium,则将 currentAdd 赋值给 maxium,若 currentAdd 为负数,则将其置于 0。这样就能狗找出子序列的最大和。

因此,我们可以避免使用数组存储数据,而是动态处理输入数据,解决了空间复杂度问题。

  除了找出子序列的最大和值之外,题目中还要求找出输出这个子序列的第一个元素和最后一个元素。因此需要一个标记记录子序列的首尾元素。因为子序列的首元素由 currentAdd 决定,因此它随着该变量的变化而变化,尾元素则随着 maxium 被找到而变化,记录当前的输入的元素。

  由于在序列中找到的正数不一定是最大值,所以我们需要额外的变量记录首尾元素,直到子序列的和比之前记录的最大值还要大的时候,才将额外的变量值赋值给需要输出的首尾元素值。

  由于题目中有可能出现序列中所有元素为负数的情况,且这种情况下需要输出序列的首尾元素。因此我们需要额外的变量记录序列的第一个元素和最后一个元素。

  题目中也透露了一个不明显的信息,就是序列中子序列最大值为 0 的情况,因此也应当将其考虑进去,所以设置 maxium 为 -1,区别序列元素均为负数的情况,以及序列中子序列最大和值为 0 的情况。

实现

#include<iostream>
using namespace std;
int main() {
	int numbers;
	// 最大值记为 -1 用于处理子序列和最大值为 0 的情况
	int maxium = -1;
	int currentAdd = 0;
	int leftIndex, rightIndex;
	int leftFlag, rightFlag;
	int first, last;
	int currentNum;
	
	first = last = leftFlag = rightFlag = leftIndex = rightIndex = 0;
	// 接收输入的序列长度
	cin >> numbers;
	for (int i = 0; i < numbers; i++) {		
		// 接收序列数字
		cin >> currentNum;
		// 记录序列的开头
		if (first == 0)
			first = currentNum;
		// 记录序列的结尾
		last = currentNum;
		// 记录当前的子序列和
		currentAdd += currentNum;
		// 记录子序列的开头
		if (leftFlag == 0)
			leftFlag = currentNum;
		// 若当前子序列和为负数,则置于0
		if (currentAdd < 0) {
			leftFlag = currentAdd = 0;
			continue;
		}
		// 若当前子序列和比最大值大,则用最大值接收该子序列和,并记录子序列的开头与结尾
		if (currentAdd > maxium) {
			rightIndex = rightFlag = currentNum;
			leftIndex = leftFlag;
			maxium = currentAdd;
		}

	}
	// 若子序列的和为负数,则将子序列开头记为序列开头,子序列结尾记为序列结尾,最大值记为 0 
	if (maxium == -1) {
		leftIndex = first;
		rightIndex = last;
		maxium = 0;
	}
	
	cout << maxium << " " << leftIndex << " " << rightIndex;
	return 0;
}

希望对你有所帮助!

posted @ 2019-01-16 11:10  Intro1997  阅读(443)  评论(1编辑  收藏  举报