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;
}
希望对你有所帮助!
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从“看懂世界”到“改造世界”:AI发展的四个阶段你了解了吗?
· 协程本质是函数加状态机——零基础深入浅出 C++20 协程
· 编码之道,道心破碎。
· 记一次 .NET 某发证机系统 崩溃分析
· 微服务架构学习与思考:SOA架构与微服务架构对比分析
· C#实现语音预处理:降噪、静音检测、自动增益(附Demo源码)
· 从“看懂世界”到“改造世界”:AI发展的四个阶段你了解了吗?
· dotnetty 新的篇章- 开源
· 设计模式:简单工厂、工厂方法与抽象工厂
· 用好 JUnit 5 的高级特性:提升单测效率和质量