问题描述:
题目要求:
输出最大子列和以及最大子列和的第一个和最后一个元素。如果数列中不止一个最大子列和,只需求出最小下标的最大子列和的第一个和最后一个元素。如果全是是负数,输出最大子列和为0,并输出整个数列的第一个和最后一个元素
解决这个问题的思路是在原先求最大子列和的算法的基础上加以改进来解决这个问题(原先最大子列和代码https://www.jianshu.com/p/06681537ffe1
解决思路:
Notice:如果没有看过上方的最大子列和代码很难看懂下文
为避免误解,首先说明Max为最大子列和以及本文中First便指的是最大子列的第一个元素,也就是代码中的firstIndex,Last亦同
首先需要分析,整个最大子列和有哪几种形式,如下图所示:由上图知,给我们的最大子列和有七种形式,其中正数和零还会有顺序问题,谁先谁后的关系
现在便开始我们的分析
我们实现把Max值设置为一个特殊的负值,并收集第一项和最后一项。运行完计算程序,观察最大子列和的值,有三种情况
负数,0,正数
由于我们的最大子列和在计算中会不断更新,所以我们只需在最后进行比较,便可以确定输出的方式。
难点主要是在最大子列和为正数时最大子列前后有0无0的情况(记住要满足最小下标!
我们在最大子列一开始时,让判断条件为number >= 0(让第一个元素输出为最小下标元素),并且让正在检测的最大子列(!注意:这个是正在检测的最大子列 这和 之前所说数列的第一个元素不同!)的第一个元素赋值给tempFirst,tempLast,而更新tempLast的情况为(目的是让最后一个元素输出为最小下标元素):只有在gradient>0或者之前连续一串正整数number才会更新,当出现比原有最大子列更大时,更新First,Last
还有一点值得注意的是:
我们把Max设置为-1,但是temp却默认为0。这边让Max的更新出现了一个矛盾:如果输出数列全部为负数,便会让Max更新为0,也就是Max至少会大于等于0
所以在此代码的做法是只有temp > 0,才会更新Max。但是随之带来一个问题 如果Max就是0怎么办?所以增加一个判断是否为0的变量来表示最大子列和是否为0。通过判断hasZero来更新Max,First,Last
Code
#include<stdio.h>
#include<math.h>
int main(void) {
int mark;
int length;
int Max = -1;
int gradient = 0;
int number;
int temp = 0;
int firstIndex;
int lastIndex;
int tempFirst;
int tempLast;
int isFirst = 1;
int hasZero = 0;
scanf("%d", &length);
for (int i = 0; i < length; i++) {
scanf("%d", &number);
//第一个数字都填充到Max,last
if (i == 0) {
firstIndex = lastIndex = number;
}
if (number >= 0) {
//如果全是正数
if (number == 0) {
hasZero = 1;
}
if (isFirst) {
tempFirst = tempLast = number;
isFirst = 0;
}
else if (number > 0) {
tempLast = number;
}
temp += number;
}
else {
for (mark = i; mark < length; mark++) {
gradient += number;
if (number == 0) {
hasZero = 1;
}
if (gradient > 0) {
//有正有负
tempLast = number;
temp += gradient;
gradient = 0;
}//当前最大子列和爆了,什么都不做
else if (-gradient > temp) {
if (temp > Max) {
if (temp > 0) {
Max = temp;
firstIndex = tempFirst;
lastIndex = tempLast;
}
else if (hasZero) {
Max = firstIndex = lastIndex = 0;
}
}
isFirst = 1;
gradient = temp = 0;
break;
}
scanf("%d", &number);
}
i = mark;
}
}
if (temp > Max && temp > 0) {
Max = temp;
firstIndex = tempFirst;
lastIndex = tempLast;
}
//如果都是负数
if (Max == -1) {
lastIndex = number;
Max = 0;
}
printf("%d %d %d\n", Max, firstIndex, lastIndex);
return 0;
}