问题描述
这是一个经典问题
题目链接PAT_A1007
题目大意:输入K个数,找出其中和最大的连续子数列,并输出这个子数列的和、这个数列的第一个数、这个数列的最后一个数。
如果最大和不唯一,输出最左边的和为最大和的子数列的首、尾数字。
如果一整个数列都为负数,输出0 数列第一个数 数列最后一个数
解决方法
想了想此问题不用开一个数组去存储,所以使用在线处理的方式。
#include<cstdio>
int main() {
int K, num, first, last, isum=0, tfirst, tlast, tsum=0, mfirst;
int nflag = 1;
scanf("%d", &K);
for (int i=0; i<K; ++i) {
scanf("%d", &num);
if (i == 0) mfirst = num;
if (num >= 0) nflag = 0;
if (tsum == 0) {
tfirst = tlast = num;
}
tsum += num;
tlast = num;
if (tsum > isum) {
first = tfirst;
last = tlast;
isum = tsum;
} else if (tsum < 0) {
tsum = 0;
}
}
if (nflag == 1) printf("0 %d %d", mfirst, tlast);
else if (isum == 0) printf("0 0 0");
else printf("%d %d %d", isum, first, last);
return 0;
}
其中tfirst, tlast, tsum代表暂时储存的一个解,first, last, isum代表整个数组的最优解。
时间复杂度O(n), 空间复杂度O(1)
坑点
其实在线解决的方案牵涉到的逻辑比我想象中的复杂
卡在一种特例上:
输入:
3
-2 0 -3
应该输出的是0 0 0,而我之前的代码输出的是0 -2 -3
即 0 在一堆负数里的时候。
这个卡了很久。