这个题的思路比较简单,说一说怎么从暴力优化
法一: 暴力 O(nk)
如下:
class Solution {
public:
int maxResult(vector<int>& nums, int k) {
int len=nums.size();
int dp[len]; dp[0]=nums[0];
for(int i=1;i<len;i++){
int tmp=INT_MIN;
for(int j=i-1;j&&j>=i-k;j--){
tmp=max(tmp,dp[j]);
}
dp[i]=tmp+nums[i];
}
return dp[len-1];
}
};
法二: 单调队列 O(n)
暴力当然很easy,但是会超时, 但是我们发现其实时间消耗主要是在寻找当前窗口的最大值上,那么有没有一种结构能够在O(1)的时间复杂度下找到最大值呢 ----->单调队列
by the way,单调栈能做的,单调队列都能, 单调栈不能做的,单调队列也能做.
还是一样的模板:
int len=nums.size();
deque<int> dq;
int dp[len];
for(int i=0;i<len;i++){
while(dq.size() && 限制){//一般是对队头不满足条件的进行删除
dq.pop_front();
}
//1.
while(dq.size() && dp[i]比较dp[dq.back()]){ //一般是对队尾进行处理,维护最大/最小
dq.pop_back();
}
//2.
dq.push_back(i);
//3.
}
根据条件选择是在 1.2.3. 哪里进行dp的更新
代码如下:
class Solution {
public:
int maxResult(vector<int>& nums, int k) {
int len=nums.size();
deque<int> dq;
int dp[len];
//我们可以发现其实是取到tmp的时间复杂度是O(k),导致超时,所以我们使用一个数据结构来优化这一个过程
//单调队列dq保存当前dp[j](j=i-k...i-1)的最大值
for(int i=0;i<len;i++){
while(dq.size() && i-dq.front()>k){//首先去除那些不满足j的范围的元素
dq.pop_front();
}
//如果在这里处理,那么dq.front就是当前不包括i的dp最大值
//而且在这里处理也可能出现dq为空的情况
//所以我们在这里处理
if(dq.size()) dp[i]=dp[dq.front()] + nums[i];
else dp[i]=nums[i];
while(dq.size() && dp[i]>=dp[dq.back()]){
dq.pop_back();
}
//如果在这里处理,那么dq.front就是当前不包括i的dp最大值
//但是在这里处理也可能出现dq为空的情况
dq.push_back(i);
//如果在这里处理 那么dq.front就是当前包含i的dp最大值
}
return dp[len-1];
}
};