Max Sum 2 Subarray
给定一个整数数组,找出两个不重叠子数组使得它们的和最大。
每个子数组的数字在数组中的位置应该是连续的。
返回最大的和。
样例
给出数组[1, 3, -1, 2, -1, 2],这两个子数组分别为[1, 3]和[2, -1, 2]或者[1, 3, -1, 2]和[2],它们的最大和都是7
注意
子数组最少包含一个数
挑战
要求时间复杂度为O(n)
Solution
类似max subarray I的解法,区别是我们这里扫两遍,从左边向右边的时候算出globalmax,从右边向左边的时候算出localMax,然后找两边加起来的最大值。首先我们定义两个变量,localMax[i]为以i结尾的subarray中最大的值,globalMax[i]定义为[0, i]范围中最大的subarray(subarray不一定需要以i结尾)。递推表达式是:
- localMax[i] = max(localMax[i - 1] + A[i], A[i]);
- globalMax[i] = max(globalMax[i - 1], localMax[i]);
从右边向左边的时候维护localMax[i],这时的localMax[i]指的是以i开头的最大的subarray
- localMax[i] = max(localMax[i + 1] + A[i], A[i]);
扫两遍,时间复杂度O(n),空间复杂度O(n),从右边向左边扫的时候不需要开辟一个新的数组,并且计算最后最大值可以在第二次循环的时候一起做了
Code
public class Solution {
/**
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
public int maxTwoSubArrays(ArrayList<Integer> nums) {
if (nums == null)
return 0;
int len = nums.size(), currSum = 0;
int[] left = new int[len];
for (int i = 0; i < len - 1; i++) {
int sum = currSum + nums.get(i);
if (i == 0)
left[i + 1] = sum;
else
left[i + 1] = sum > left[i]? sum: left[i];
currSum = sum <= 0? 0: sum;
}
currSum = 0;
int max = Integer.MIN_VALUE;
for (int i = len - 1; i > 0; i--) {
int sum = currSum + nums.get(i);
if (sum + left[i] > max)
max = sum + left[i];
currSum = sum <= 0? 0: sum;
}
return max;
}
}