原题链接:连续子数组的最大和(二)_牛客题霸_牛客网
描述:
输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。
1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个
3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组
4.返回的数组不计入空间复杂度计算
数据范围:
1<=n<=10^5
-100 <= a[i] <= 100
要求:时间复杂度O(n),空间复杂度O(n)O
进阶:时间复杂度O(n),空间复杂度O(1)O
解题思路:
解体分为两步,
第一步是保证找出具有最大和的连续子数组。
第二步是如果有相同的连续子数组,找出长度最长的
第一步,找出具有最大和的连续子数组
记录两个指针,一个start,一个end,以及一个当前求和值sum和历史最大求和值lastMaxSum。如果end++依次遍历,如果当前值
array[end]>0时,说明这个值肯定要计入连续子数组的,并且如果当前的sum值大于之前的lastMaxSum,则更新最大连续子数组的范围,然后继续end++遍历。
array[end]<0时,则只更新当前sum值即可,因为当前sum不可能大于lastMaxSum。如果sum<0,则说明之前的连续子数组都可以不要了。则更新start值。重新开始计算。
array[end]==0时,在一步中无需处理。
第二步,找出长度最长的。
加入判断条件,如果sum=lastMaxSum时,要判断当前长度和历史最大值的连续子数组长度。
代码:
public int[] FindGreatestSumOfSubArray(int[] array) {
int max = -101;
for (int value : array) {
if (value > max) {
max = value;
}
}
if (max < 0) {
return new int[]{max};
}
int[] maxRnage = new int[2];
int lastMaxSum = 0;
int start = 0;
int end = 0;
int sum = 0;
//还差一个场景就是后面的sum值相同时长度前面的长
while (end < array.length) {
int current = array[end];
if (current > 0) {
sum += current;
//更新最大值
end++;
if (sum > lastMaxSum) {
lastMaxSum = sum;
maxRnage[0] = start;
maxRnage[1] = end;
} else if (sum == lastMaxSum) {
//判断长度
if ((maxRnage[1] - maxRnage[0]) < (end - start)) {
//更新位置
maxRnage[0] = start;
maxRnage[1] = end;
}
}
} else if (current < 0) {
sum += current;
//全部清空
end++;
if (sum < 0) {
start = end;
sum = 0;
}
} else {
//判断长度
if ((maxRnage[1] - maxRnage[0]) <= (end + 1 - start) && sum == lastMaxSum) {
//更新位置
maxRnage[0] = start;
maxRnage[1] = end + 1;
} else if (sum <= 0) {
start = end;
}
end++;
}
}
start = maxRnage[0];
end = maxRnage[1];
int[] ints = new int[end - start];
System.arraycopy(array, start, ints, 0, end - start);
return ints;
}