题目基本要求:
-
输出最大子列和结果
-
输出最大子列的头和尾(若结果不唯一,要输出出现最大子列最早的那两个数字)
-
若全为负数则输入整个数列的首个数字和末尾数字(下面用左标和右标表示)
-
若为单个数,则左右都取这个数
注意:这里有个坑点(有一段0在最大的子列前面的的话,头要取到0)举个例子:0 0 0 0 1 2 3 4 0 -10 结果是:10 0 4最大子列的特点:最大子列中第一个数可以为0,但是不可以为负数,而最后一个数字不可以为0(题意:取出现最早的),也不能为负数,凭借这个我们可以在最后判断一下一些特殊情况。
代码如下:
#include<stdio.h>
int main(){
int tip = 0; //用来判断当下是否需要改变左列首位记录
int maxleft = -1;//用于保留最大子列的最左的数字
int K = 0;
long this_num = 0,max_num = 0; //记录当下值和最大值
int left = -1,right = 0; /*记录左标和右标
左标是根据this_num为0的时候进行改值,而右标是根据取到最大子列的时候进行改值
左标要不断的改,所以要有变量记录最大子列的左标*/
scanf("%d",&K);
for(int i = 0; i < K; i++) {
int num = 0;
scanf("%d",&num);
if(i == 0) left = maxleft = num; //将最大左标和左标都取首位
if(i == K-1 && right == 0 && left < 0)//根据上述最大子列特征
right = num; //到最后一步的时候判断一下,右标是否为0(根本没变过值),和left是否小于0
//这个情况是为了防止所有的数字都为负数
if(this_num == 0 && num >= 0 && tip == 0){
//注意左位可取0,tip是防止0无法赋值给left(若没有tip提示,上述例子的结果是 10 1 4)
left = num;
tip = 1; //改变tip值是为了停止改变左值,说明先处于累加求和的状态。
}
this_num += num; //累加
if(this_num > max_num) { //若进入了这个判断体,就要保留最大值,和最大子列左标和右标
max_num = this_num;
right = num;
maxleft = left;
} else if(this_num < 0) { //若进入了这个判断体,就要将当下和变为0,和准备记录新的左标
this_num = 0;
tip = 0;
}
}
//最后是为了防止只有一个零,而其余全是负数的时候,这时候左右标都得取0(有特性可知,左标可以被赋值到0,但右标不可)
if(left == 0 && right == 0) {
maxleft = right = 0 ;
}
printf("%ld %d %d",max_num,maxleft,right);
}
数据结构还是很有意思的,fighting!