Ina given array nums ofpositive integers, find three non-overlapping subarrays with maximum sum.
Eachsubarray will be of size k, and we want to maximize the sum of all 3*k entries.
Returnthe result as a list of indices representing the starting position of eachinterval (0-indexed). If there are multiple answers, return thelexicographically 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.
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).
这题研究了相当久,最后一次就ac了,我也没想到这么复杂的dp一次就能ac,这题当然也有简单的方法,简单的方法就是利用分组的特性,将nums分为left,middle,right三组,
left[i]用来求nums从左到右0~i-1最大的一个分组,
right[i]表示nums从右到左i~n-1最大的分组,
这样middle[i]表示当中间一组取起点为i的变量的时候最大的三组,这样取所有left[i-1]+nums[i]+right[i+1]中最大的一个就能得到最终的结果,时间为O(n),这种方法虽然简单,但是适用性很窄,只适用3组的情况。
接下来的方法适用于m组,每组长度为k的情况,dp[t][i]表示t组,0~i-1范围类t组最大的和,store[t][i]表示0~i-1范围t组最大和方案最后一组选择的index,那么可知theNumSum[i],表示nums中从nums[i]开始累加累加k次之后的值,那么可知 dp[t][i]=max(dp[t-1][i-k]+theNumSum[i-k],dp[t][i-1]),的值,这样不断是用dp,直到dp[m][n](n为nums的长度)得到之后,dp[m][n]就是最大的和,但是得到最大和还不够,还需要最大和方案,这个时候store就派上了用场,按照程序中的方法检索store,就能得到最终的结果,这个算法的时间复杂度为O(mn),m为分组的个数,可知,仍然是线性时间复杂度
class Solution { public: vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) { vector<int> dp[2]; int n = nums.size(); int index; int howMany = 3;//howmany表示分组的个数 dp[0] = vector<int>(n + 1, 0); dp[1] = vector<int>(n + 1, 0); vector<vector<int>> store(howMany + 1, vector<int>(n + 1, 0)); vector<int> result; vector<int> theSum(n, 0); theSum[0] = 0; for (int i = 0; i < k; i++) { theSum[0] += nums[i]; } for (int i = 1; i <= n - 1-k+1; i++) { theSum[i] = theSum[i - 1] - nums[i - 1] + nums[i + k-1]; } for(int l=1;l<=howMany;l++) for (int i = 1 + l*k - 1; i <= n; i++) { index = (l - 1) % 2; int a = dp[index][i - k] + theSum[i - k]; int b = dp[l % 2][i - 1]; if (a > b) { dp[l % 2][i] = a; store[l][i] = i - k+1; } else { dp[l % 2][i] = b; store[l][i] = store[l][i-1]; } } index = n; for (int i = howMany; i >= 1; i--) { result.push_back(store[i][index]-1); index = store[i][index] - 1; } n = result.size(); for (int i = 0; i < result.size() / 2; i++) { swap(result[i], result[n - 1 - i]); } return result; } };