In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum.
Each subarray will be of size k, and we want to maximize the sum of all 3*k entries.
Return the result as a list of indices representing the starting position of each interval (0-indexed). If there are multiple answers, return the lexicographically smallest one.
Example:
Input: [1,2,1,2,6,7,5,1], 2
Output: [0, 3, 5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.
三个不重叠的subarrays,
我们可以划分为三个区间 [0…i-1] [i… i +k-1] [i+k …]
从这个区间开始枚举 [0…k-1] [k…2k-1] [2k …]
事先先算好从左边过来,最大的 size为k的窗口的值,对应的Index
从右边过来,最大的 size为k的窗口的值,对应的Index
就枚举中间这个k大小的窗口,复杂度为O(N)
此题的下标太乱很容易错,一定要把区间画出来
另外注意从右边过来的时候,max值相等,要替换(因为我们求从左边来最小的Index)
public int[] maxSumOfThreeSubarrays(int[] nums, int k) {
int n = nums.length;
int[] sums = new int[n+1];
sums[0] = 0;
for(int i = 0; i< nums.length;i++) {
sums[i+1] = sums[i] + nums[i]; //sums[i], i前面所有的数之和,不包括i
} // 本题也可以直接求出 size 为k的窗口的和
int[] left = new int[n]; int[] right = new int[n];
int max = Integer.MIN_VALUE;
for(int i=0;i<nums.length-k;i++) {
int cur = sums[i+k] - sums[i];
if(cur > max) { //大于号,因为相等的话不用替换
left[i] = i; //left[i]: i+k之前的数中 k大小的窗口里最大时,起始index
max = cur;
} else {
left[i] = left[i-1];
}
}
max = Integer.MIN_VALUE;
for(int i = nums.length - k; i>=0;i--) {
int cur = sums[i+k] - sums[i];
if(cur >= max) { //大于等于号,因为相等的话需要替换
right[i] = i; //right[i]: i之后的数中 k大小的窗口里最大时,起始index
max = cur;
} else {
right[i] = right[i+1];
}
}
int[] res = new int[3]; max = Integer.MIN_VALUE;
for(int i=k; i<=nums.length-k*2;i++) {
int l = left[i-k], r = right[i+k];
int cur = sums[l+k] - sums[l] + sums[r+k] -sums[r] + sums[i+k] - sums[i];
if(cur > max) {
res[0] = l; res[1] = i; res[2] = r;
max = cur;
}
}
return res;
}