Given an integer array nums and an integer k, find three non-overlapping subarrays of length k with maximum sum and return them.
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 1:
Input: nums = [1,2,1,2,6,7,5,1], k = 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.
Example 2:
Input: nums = [1,2,1,2,1,2,1,2,1], k = 2
Output: [0,2,4]
Constraints:
- 1 <= nums.length <= 2 * 104
- 1 <= nums[i] < 216
- 1 <= k <= floor(nums.length / 3)
直接用 dp 来解会超时, 想了半天也没想到优化的办法。开始看答案。答案不难理解, 但是如果没有提示, 恐怕自己很难会往这个方向去想。
首先我们定义一个数组 w, w[i]代表从 nums[i]到 nums[i+k-1]的加和, 然后我们再对 w 做 prefix sum 和 suffix sum, 分别是 left 和 right, 这时要注意, 这两个 sum 中都是保存的最大值的 index, 也就是说 left[i]代表的是从 w[0]到 w[i]中最大值的 index, right[i]代表的是从 w[i]到 w[last]的最大值的 index, 无论是 left 还是 right, 相同的 w[i]值取相对小的 index。然后假设我们通过三个值,i, j, l, 将 w 分成三份, 那中间的 j 的取值范围就是 k < j < w.len() - k, 这时左边那部分的最大值就是 w[left[j-k]], 也就是从 w[0]到 w[j-k]中的最大值, 右边那部分的最大值是 w[right[j+k]], 也就是从 w[j+k]到 w[last]中的最大值, 中间部分的值是 w[j], 遍历 j, 每次将这三部分相加,取最大值即可
impl Solution {
pub fn max_sum_of_three_subarrays(nums: Vec<i32>, k: i32) -> Vec<i32> {
let mut w = vec![0; nums.len() - k as usize + 1];
let mut queue: Vec<i32> = Vec::new();
let mut sum = 0;
for i in 0..nums.len() {
queue.push(nums[i]);
sum += nums[i];
if queue.len() > k as usize {
sum -= queue.remove(0);
}
if queue.len() == k as usize {
w[i + 1 - k as usize] = sum;
}
}
let mut max = 0;
let mut left = vec![0; w.len()];
for i in 0..w.len() {
if w[i] > w[max] {
max = i;
}
left[i] = max;
}
max = w.len() - 1;
let mut right = vec![0; w.len()];
for i in (0..w.len()).rev() {
if w[i] >= w[max] {
max = i;
}
right[i] = max;
}
let mut ans = Vec::new();
let mut max = 0;
for j in k as usize..w.len() - k as usize {
if w[left[j - k as usize]] + w[j] + w[right[j + k as usize]] > max {
max = w[left[j - k as usize]] + w[j] + w[right[j + k as usize]];
ans = vec![left[j - k as usize] as i32, j as i32, right[j + k as usize] as i32];
}
}
ans
}
}