Leetcode 1696. Jump Game VI (DP + 单调队列)

  1. Jump Game VI
    Medium
    You are given a 0-indexed integer array nums and an integer k.

You are initially standing at index 0. In one move, you can jump at most k steps forward without going outside the boundaries of the array. That is, you can jump from index i to any index in the range [i + 1, min(n - 1, i + k)] inclusive.

You want to reach the last index of the array (index n - 1). Your score is the sum of all nums[j] for each index j you visited in the array.

Return the maximum score you can get.

Example 1:

Input: nums = [1,-1,-2,4,-7,3], k = 2
Output: 7
Explanation: You can choose your jumps forming the subsequence [1,-1,4,3] (underlined above). The sum is 7.
Example 2:

Input: nums = [10,-5,-2,4,0,3], k = 3
Output: 17
Explanation: You can choose your jumps forming the subsequence [10,4,3] (underlined above). The sum is 17.
Example 3:

Input: nums = [1,-5,-20,4,-1,3,-6,-3], k = 2
Output: 0

Constraints:

1 <= nums.length, k <= 105
-104 <= nums[i] <= 104

解法1:DP。会超时

class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> dp(n + 1, INT_MIN);
        dp[0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= k; j++) {                
                if (i >= j) {
                    dp[i] = max(dp[i], dp[i - j] + nums[i - 1]);
                }
            }
        }
        return dp[n];
    }
};

解法2:DP+单调队列。
注意:

  1. 这里的单调队列是针对DP数组(而不是原数组nums)来处理。
  2. dq本身既是单调队列,又是滑动窗口。
  3. 直接用dp[i]=nums[i] + dp[dq.front()]。不要用dp[i]=max(dp[i], nums[i] + dp[dq.front()])。因为dp[dq.front()]本身就是滑动窗口里面的最小值了。加了max反而逻辑不对。
  4. dp[i]必须在 while (!dq.empty() && dp[dq.back()] < dp[i]) 之前先算出来,不然dp[i]是初始值INT_MIN,肯定不对。而因为窗口大小不能>k,所以在计算dp[i]之前必须有一个循环pop_front()。
class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        int n = nums.size();
        int res = INT_MIN;
        vector<int> dp(n, INT_MIN);
        dp[0] = nums[0];
        deque<int> dq;
        dq.push_back(0);
        for (int i = 1; i < n; i++) {
            while (i - dq.front() > k) dq.pop_front();
            dp[i] = nums[i] + dp[dq.front()];  //不要用dp[i]=max(dp[i], nums[i] + dp[dq.front()])
            while (!dq.empty() && dp[dq.back()] < dp[i]) {
                dq.pop_back();
            }
            dq.push_back(i);
        }
        return dp[n - 1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值