网站新闻标题字数,网站建设服务外包,巨鹿做网站哪家好,不用服务器做网站这道题使用动态规划
解法一#xff1a;非常规的动态规划
这道题相当于选出3个长度为k的子数组#xff0c;要求子数组和最大#xff0c;返回的是每个子数组的第一个元素的下标。 首先#xff0c;求所有长度为k的子数组的和#xff0c;即sum#xff0c;并将结果存储在对应…这道题使用动态规划
解法一非常规的动态规划
这道题相当于选出3个长度为k的子数组要求子数组和最大返回的是每个子数组的第一个元素的下标。 首先求所有长度为k的子数组的和即sum并将结果存储在对应首个元素索引下例如 输入[1,2,1,2,6,7,5,1], 2 则sum {3,3,3,8,13,12,6} 如果nums数组长度为n则sum数组长度为n-k1 然后思考找到3个长度为k的数组并要求子数组和最大在已经得到了sum的情况下可以转化为求sum中3个原元素位置不重叠且3个sum元素值和最大。 这里假设选中sum[i]那么只需要求其左右两边最大的sum值但是注意其下标要不和i重叠即至少小于等于i-k和大于等于ik。
于是设置两个数组left和rightleft[i]表示从0到i的sum[i]最大值的下标right[i]表示从n-1到i的sum[i]最大值的下标注意这里的下标都是sum数组的下标而不是nums数组的。 于是3个选中的sum值的和就应该是 sum[left[i-k]] sum[i] sum[right[ik]]
其中以k 2为例sum[i]相当于nums[i], nums[i1]而sum[left[i-k]]相当于nums[i-2], nums[i-1]sum[right[ik]]相当于nums[i2],nums[i3]这样就保证了元素的不重叠。
另外这里求sum数组的时候并没有使用N*N复杂度的计算而是采用了首先设定一个初始值然后依次相加相减得到复杂度降低。
class Solution {
public:vectorint maxSumOfThreeSubarrays(vectorint nums, int k) {vectorint sum;int cnt 0;for (int i 0; i k; i) {cnt nums[i];}sum.push_back(cnt);for (int i k; i nums.size(); i) {cnt nums[i] - nums[i - k];sum .push_back(cnt);}vectorint ans(3);int n sum.size(); // 注意是sum的长度vectorint left(n, 0);vectorint right(n, n - 1);for (int i 1; i n; i) {if(sum[i] sum[left[i - 1]]) left[i] i;else left[i] left[i - 1];}for (int i n - 2; i 0; --i) {if(sum[i] sum[right[i 1]]) right[i] i;else right[i] right[i 1];}int mx 0;for (int i k; i n - k; i) {if (mx sum[left[i - k]] sum[i] sum[right[i k]]) {mx sum[left[i - k]] sum[i] sum[right[i k]];ans {left[i - k], i, right[i k]};}}return ans;}
};解法二倒序动态规划
首先思考正常的动态规划的思路 将i从0开始遍历分别计算f(i)的值而f(i)表示以索引值为i的元素为结尾的区间得出的结果是索引值i更大的区间 在这道题中我们设置f[i][j]表示以第i个元素为结尾的区间中包含j个不重叠子数组的和分两种情况讨论
不包含Ai则f[i][j] f[i-1][j]包含Ai相当于包含了[i-k, i]之间的元素区间则f[i][j] f[i-k][j-1] (Si - Sk)S表示前缀和
f[i][j]在其中取最大值。 上述过程有一种从右向左迭代的感觉
而由于题目里要求字典序从小到大于是就要使用倒序DP 那么i就变为从末尾向前遍历而f(i)也变成了以第i个元素为开头的区间迭代从右向左变成了左向右于是上述两种情况就变成了
不包含Ai则f[i][j] f[i1][j]包含Ai相当于包含了[i, ik]之间的元素区间则f[i][j] f[ik][j-1] (Sik - Si)S表示前缀和
然后再确定好x区间上届遍历即可找到答案。
class Solution {
public:vectorint maxSumOfThreeSubarrays(vectorint nums, int k) {vectorint ans;int n nums.size();vectorint s(n 1);for (int i 1; i n 1; i) {s[i] s[i - 1] nums[i - 1];}int x n 1;vectorvectorint f(n 2, vectorint(4));for (int i n - k 1; i 0; --i) {for (int j 1; j 3; j) {f[i][j] max(f[i 1][j], f[i k][j - 1] s[i k - 1] - s[i - 1]);// 注意s的下标}if (f[x][3] f[i][3]) x i; // 这步是必须的确定最小下标}int y 3;while (y 0) {while (f[x][y] ! f[x k][y - 1] s[x k - 1] - s[x - 1]) x;// 注意s的下标ans.push_back(x - 1);x k;--y;}return ans;}
};