week18
题目
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.
Note:
nums.length will be between 1 and 20000.
nums[i] will be between 1 and 65535.
k will be between 1 and floor(nums.length / 3).
原题地址:https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/description/
解析
题目要求给定一个数组和常数k,找出三个不重叠的长度为k的子数组使得这三个子数组的和最大。
大致思路是先遍历一次数组得到以每个位置为起始位置的长度为k的数组的和,再遍历一次,每次固定以当前位置为起始位置的子数组作为三个数组中的中间一个,找到当前情况下的第一个和第三个数组使得和最大,如果该情况大于先前得到的以其他位置为中间数组起始位置的和的最大值,则记录三个数组的起始位置并将最大值替换。
代码
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
int len = nums.size();
int maxSum = 0;
vector<int> res(3, -1);
vector<int> sum;
Sum(nums, sum, k);
for (int i = k; i <= (len - 2 * k); ++i) {
int end = i - k;
int pos1;
// 找到固定了以i为起始位置的子串作为三个子串的中间子串,第一个子串的最大值
findLargest(sum, 0, end, pos1);
int begin = i + k;
int pos2;
// 找到固定了以i为起始位置的子串作为三个子串的中间子串,第三个子串的最大值
findLargest(sum, begin, len - k, pos2);
// 以i为起始位置的子串作为三个子串的中间子串
// tmp为该种情况所能达到的最大值
int tmp = sum[pos1] + sum[i] + sum[pos2];
if (tmp > maxSum) {
maxSum = tmp;
res[0] = pos1;
res[1] = i;
res[2] = pos2;
}
}
return res;
}
// 返回以每个位置为起始点的子串的和
void Sum(vector<int>& nums, vector<int>& sum, int k) {
sum.clear();
int len = nums.size();
int tmp = 0;
for (int i = 0; i < k; ++i) {
tmp += nums[i];
}
sum.push_back(tmp);
for (int i = 1; i <= (len - k); ++i) {
tmp = tmp - nums[i - 1] + nums[i + k - 1];
sum.push_back(tmp);
}
}
// 返回从起始位置为begin到起始位置为end的子串的和中的最大值
// pos记录该起始位置
void findLargest(vector<int>& sum, int begin, int end, int& pos) {
pos = begin;
int largest = sum[begin];
for (int i = begin + 1; i <= end; ++i) {
if (sum[i] > largest) {
largest = sum[i];
pos = i;
}
}
}
};