1696.跳跃游戏 VI

        这个题的思路比较简单,说一说怎么从暴力优化

法一: 暴力 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];
    }
};

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值