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.
题目的意思是: 给定一个数组,找到其中3个不相互覆盖的子串,使其和最大,返回3个子串的位置。如果子串和相等,返回最前面的子串位置。给定子串的长度为k。
做法:动态规划。首先对数组预处理,以k为基准,得到一个子串求和的数组new_nums。对这个数组进行动态规划。dp[i][j]代表 以i为结尾,个数为j的最大值。转移方程是 dp[i][j] = max(dp[0][j-1],...,dp[i - k][j-1]) + new_nums[i]; 但是,这么做复杂度是O(n*n)。数据有2w个,不一定能过。使用一个变量cnt_max,记录从第一个位置到(i-k)的最大值,如果大于cnt_max的值时,则更新。 最后,利用dp和new_nums得到子串的位置。
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
int dp[20010][4];
memset(dp, 0, sizeof(dp));
int n = nums.size();
int new_n = n - k + 1;
vector <int> answer(3);
int max_sum = 0;
int max_id;
vector <int> new_nums;
int cnt = 0;
for(int i=0;i<k;i++){
cnt += nums[i];
}
new_nums.push_back(cnt);
for(int i=0;i<new_n - 1;i++){
cnt = cnt - nums[i] + nums[i + k];
new_nums.push_back(cnt);
}
for(int i =0;i<new_n;i++){
dp[i][1] = new_nums[i];
}
int cnt_max = 0;
for(int i = k; i < new_n; i++){
if( dp[i - k][1] > cnt_max ){
cnt_max = dp[i - k][1];
}
dp[i][2] = cnt_max + new_nums[i];
}
cnt_max = 0;
for(int i = 2 * k; i < new_n; i++){
if( dp[i - k][2] > cnt_max ){
cnt_max = dp[i - k][2];
}
dp[i][3] = cnt_max + new_nums[i];
if(dp[i][3] > max_sum){
max_sum = dp[i][3];
max_id = i;
}
}
answer[2] = max_id;
int now_sum = max_sum - new_nums[max_id];
for(int i = 0; i< new_n; i++){
if( dp[i][2] == now_sum){
answer[1] = i;
now_sum -= new_nums[i];
break;
}
}
for(int i=0; i< new_n; i++){
if(dp[i][1] == now_sum){
answer[0] = i;
break;
}
}
return answer;
}
};