![5e56cabf61b30e8cf9c17f62b0dd2b82.png](https://i-blog.csdnimg.cn/blog_migrate/2cf6816d613a62e5eab1d710bef148fc.jpeg)
题目描述
给定数组
![equation?tex=nums](https://i-blog.csdnimg.cn/blog_migrate/a78ccf4f5caa5a8d24a36f1cd7ada47f.png)
![equation?tex=k](https://i-blog.csdnimg.cn/blog_migrate/9d4a1163d2eb1bb72228d1279049c2d8.png)
![equation?tex=3k](https://i-blog.csdnimg.cn/blog_migrate/f964ed864f9203adbbac06f9012fc546.png)
示例1
输入:
[1,2,1,2,6,7,5,1], 2
输出:
[0, 3, 5]
解释:
子数组 [1, 2], [2, 6], [7, 5] 对应的起始索引为 [0, 3, 5]。
我们也可以取 [2, 1], 但是结果 [1, 3, 5] 在字典序上更大。
提示
-
的范围在[1, 20000]之间。
-
的范围在[1, 65535]之间。
-
的范围在 [1, floor(nums.legth / 3)]之间。
题解
首先看数据范围,这题不能使用暴力,暴力时间复杂度是
![equation?tex=O%28n%5E3%29](https://i-blog.csdnimg.cn/blog_migrate/0525fd58fe008132d8ef1f528064149e.png)
下面考虑一般情况,也就是求解划分成
![equation?tex=N](https://i-blog.csdnimg.cn/blog_migrate/390824601cf6d50933744af0e4ccf208.png)
假设到第
![equation?tex=i](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
![equation?tex=dp%5Bi%5D%5Bj%5D](https://i-blog.csdnimg.cn/blog_migrate/0daf8600d3433306e88953695c87123f.png)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
然后就要寻找状态转移方程。对于第
![equation?tex=i](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png)
如果取,那就说明
![equation?tex=nums%5Bi%5D](https://i-blog.csdnimg.cn/blog_migrate/a78ccf4f5caa5a8d24a36f1cd7ada47f.png%5Bi%5D)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
![equation?tex=++++dp%5Bi%5D%5Bj%5D+%3D+dp%5Bi-k%5D%5Bj-1%5D+%2B+nums_%7Bi-k%2B1%3Ai%7D+%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/f652046d4999e5c5dca43f8621f8154d.png)
也就是说,从
![equation?tex=i-k%2B1](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png-k%2B1)
![equation?tex=i](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png)
![equation?tex=k](https://i-blog.csdnimg.cn/blog_migrate/9d4a1163d2eb1bb72228d1279049c2d8.png)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
![equation?tex=i-k](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png-k)
![equation?tex=j-1](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png-1)
如果不取,那问题就变成了求到第
![equation?tex=i-1](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png-1)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
![equation?tex=++++dp%5Bi%5D%5Bj%5D+%3D+dp%5Bi-1%5D%5Bj%5D+++%5C%5C](https://i-blog.csdnimg.cn/blog_migrate/4f738f9315888c20e4a243c800513fe3.png)
当然这题还需要你还原出最大和的情况下,所有子数组的起始元素下标,所以需要另外用一个数组保存一下每一步的最优下标。
同样,假设到第
![equation?tex=i](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
![equation?tex=path%5Bi%5D%5Bj%5D](https://i-blog.csdnimg.cn/blog_migrate/882081e18d0a5d0716c67695403a1b63.png)
![equation?tex=j](https://i-blog.csdnimg.cn/blog_migrate/ebe2c52df33e9163198c974359a197f2.png)
那么按照上面的推断,如果取第
![equation?tex=i](https://i-blog.csdnimg.cn/blog_migrate/b1677f9423a31be742701330c190cf05.png)
![equation?tex=path%5Bi%5D%5Bj%5D%3Di](https://i-blog.csdnimg.cn/blog_migrate/882081e18d0a5d0716c67695403a1b63.png%3Di)
![equation?tex=path%5Bi%5D%5Bj%5D%3Dpath%5Bi-1%5D%5Bj%5D](https://i-blog.csdnimg.cn/blog_migrate/882081e18d0a5d0716c67695403a1b63.png%3Dpath%5Bi-1%5D%5Bj%5D)
最后就是根据
![equation?tex=path](https://i-blog.csdnimg.cn/blog_migrate/03dde96f4cd575a67c8655478eb71183.png)
首先最后一个子数组的末尾元素下标一定是
代码
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
int len = nums.size(), N = 3;
int sum[len], s = 0;
for (int i = 0; i < k; ++i) {
s += nums[i];
sum[i] = 0;
}
sum[k-1] = s;
for (int i = k; i < len; ++i) {
s += nums[i] - nums[i - k];
sum[i] = s;
}
int dp[len][N+1], path[len][N+1];
memset(dp, 0, sizeof dp);
dp[k-1][1] = sum[k-1];
path[k-1][1] = k - 1;
for (int i = k; i < len; ++i) {
for (int j = 1; j <= N; ++j) {
dp[i][j] = dp[i-1][j];
path[i][j] = path[i-1][j];
if (dp[i][j] < dp[i-k][j-1] + sum[i]) {
dp[i][j] = dp[i-k][j-1] + sum[i];
path[i][j] = i;
}
}
}
vector<int> res;
int idx = path[len-1][N];
res.push_back(idx - k + 1);
for (int i = N - 1; i > 0; --i) {
idx = path[idx-k][i];
res.push_back(idx - k + 1);
}
reverse(res.begin(), res.end());
return res;
}
};
后记
![d8156171418087e410e1081a212d38dd.png](https://i-blog.csdnimg.cn/blog_migrate/19fafdcf99c541abe0cb2b01e8add3e8.jpeg)
可以看到,时间和空间还有提升的余地。想到的可能优化方法是类似于0-1背包那样,去掉动态规划数组的第二个维度,来优化空间复杂度。
但是这是有些问题的,暂时并没有想到不增加时间复杂度下减少空间开销的方法,欢迎大家提出自己的想法。