解题思路:
最大子列和问题,题目不需要得到所有等长的子列和,相等的取前面的即可,简化了题目。最大子列和的最好时间复杂度是O(N),所以应该尽量想着一遍遍历求出答案,题目要求输出最大子列和,子列和final_sum,开始&&结束,对应的值,想到这比较符合数组的存储结构,遍历下标,start对应一个,end对应一个,再用start和end访问数组就得到结果了。除此之外还需要两个中间变量,一个是遍历过程中的sub_sum,一个index用来更新start的值,当遍历数组过程中sub_sum比final_sum大了,自然要发生一次更新,想想要怎么更新,首先是不是end要先来一下,end肯定是跟着当时遍历的最后一个数的变化的,直接更新为当时的遍历下标i即可。而start什么时候需要更新呢?sub_sum一直是最大子列和的时候不需要更新,为什么不需要?sub_sum就是最大的子列和,start要变到哪儿去?变了岂不是出错了,所以start要在中间变量的子列和sub_sum不再是最大子列和的时候才要更新,考虑这样一个数组:{1 2 3 4 -5 -23 3 7 5 -10},当遍历到5的时候,start是不是需要更新了?之前start可一直是0,但是怎么得到3(7前面)的下标呢?在遍历的时候,仅仅用遍历下标i肯定是不够的,还需要设置一个变量这个变量就是开始提到的index,index代表什么呢?想想要怎么样1+2+3+4=10=final_sum才有不会成为最大子列和?没有后面的-5和-23,它就一直会是最大子列和,因为sub_sum>0。所以当sub_sum第一次<0的时候,就要提防后面的数是不是会使1+2+3+4不再成为最大子列和,结果后面果然发生了3+7+5>10=final_sum,所以当-23加到sub_sum的时候,就需要更新sub_sum和index,此时index存储-23后面下一个正数开始的位置,而加上-23的sub_sum不管小不小于0都应该初始化为0,因为下一最大子列和(可能出现的话)肯定要从0开始算了,如果后面的子列和真的超过了前面统计的1+2+3+4,那么start就趁此机会更新为index代表的下标。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(rd.readLine());
String str[] = rd.readLine().split(" ");
int sub_sum = 0, start = 0, end = n-1, index = 0, final_sum = Integer.MIN_VALUE;
int val[] = new int[n];
for(int i=0; i<n; i++) {
val[i] = Integer.parseInt(str[i]);
sub_sum += val[i];
if(sub_sum >= 0) {
if(sub_sum > final_sum) {
final_sum = sub_sum;
if(index != start)
start = index;
end = i;
}
}
else {
sub_sum = 0;
index = i + 1;
}
}
if(final_sum < 0) final_sum = 0;
System.out.print(final_sum + " " + val[start] + " " + val[end]);
}
}