⭐算法OJ⭐跳跃游戏【动态规划 + 单调队列】(C++实现)Jump Game 系列 VI

⭐算法OJ⭐跳跃游戏【贪心算法】(C++实现)Jump Game 系列 I,II
⭐算法OJ⭐跳跃游戏【BFS+滑动窗口】(C++实现)Jump Game 系列 III,IIV

1696. Jump Game VI

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

问题理解

给定一个 0 索引 的整数数组 nums 和一个整数 k。你最初站在索引 0 处。在每一次移动中,你可以向前跳跃最多 k 步,但不能跳出数组的边界。也就是说,你可以从索引 i 跳到范围 [i + 1, min(n - 1, i + k)] 内的任意索引。

你的目标是到达数组的最后一个索引(索引 n - 1)。你的 得分 是你访问过的所有索引 j 对应的 nums[j] 的总和。

要求返回 你能获得的最大得分

解决思路

这是一个典型的动态规划问题。我们需要找到从索引 0 到索引 n - 1 的最大得分路径。

  • 状态定义:

    • dp[i] 表示从索引 0 跳到索引 i 的最大得分。
  • 状态转移:

    • 对于每个索引 i,我们需要检查从 i − k , i − 1 i - k, i - 1 i−k,i−1 范围内的所有可能的前一个位置 j,并选择使得 dp[j] + nums[i] 最大的值。
  • 状态转移方程为:
    d p i = m a x ( d p j + n u m s i ) 其中 j ∈ i − k , i − 1 dpi=max(dpj+numsi)其中j∈i−k,i−1 dpi=max(dpj+numsi)其中j∈i−k,i−1

  • 初始条件:dp[0] = nums[0],因为起点是索引 0。

  • 优化:

    • 直接使用动态规划会导致时间复杂度为 O ( n × k ) O(n×k) O(n×k),对于较大的 n n n 和 k k k 可能无法通过。
    • 可以使用单调队列 (Monotonic Queue)优化,将时间复杂度降低到 O ( n ) O(n) O(n)。
cpp 复制代码
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;

int maxResult(vector<int>& nums, int k) {
    int n = nums.size();
    vector<int> dp(n); // dp[i] 表示跳到索引 i 的最大得分
    dp[0] = nums[0];   // 初始条件
    deque<int> dq;     // 单调队列,存储索引
    dq.push_back(0);   // 初始队列

    for (int i = 1; i < n; i++) {
        // 移除不在窗口范围内的索引
        while (!dq.empty() && dq.front() < i - k) {
            dq.pop_front();
        }
        
        // 更新 dp[i]
        dp[i] = dp[dq.front()] + nums[i];
        
        // 维护单调队列
        while (!dq.empty() && dp[i] >= dp[dq.back()]) {
            dq.pop_back();
        }
        dq.push_back(i);
    }
    
    return dp[n - 1]; // 返回最后一个索引的最大得分
}

代码说明

  • 动态规划数组 dp
    • dp[i] 表示从索引 0 跳到索引 i 的最大得分。
    • 初始条件:dp[0] = nums[0]
  • 单调队列 dq
    • 用于维护当前窗口 i − k , i − 1 i - k, i - 1 i−k,i−1 内的最大值对应的索引。
    • 队列中的索引对应的 dp 值是递减的。
  • 遍历数组:
    • 对于每个索引 i,移除队列中不在窗口范围内的索引。
    • 更新 dp[i]dp[dq.front()] + nums[i]
    • 维护单调队列,确保队列中的索引对应的 dp 值是递减的。
  • 返回结果:
    • 最终返回 dp[n - 1],即最后一个索引的最大得分。

复杂度分析

  • 时间复杂度 :每个索引最多入队和出队一次,因此时间复杂度为 O ( n ) O(n) O(n)。
  • 空间复杂度 :需要额外的 dp 数组和单调队列,空间复杂度为 O ( n ) O(n) O(n)。

总结

  • 使用动态规划结合单调队列优化,可以高效地解决这个问题。
  • 时间复杂度为 O ( n ) O(n) O(n),适用于较大的输入规模。
相关推荐
致Great3 小时前
DeepSeek Harness插件开发实战教程:我让它自己写了一个 arXiv 搜索插件
算法
罗西的思考7 小时前
【Agent OS / AIOS】AOHP 深度解读:当 OS 开始为 Agent 而设计
人工智能·算法·机器学习
民乐团扒谱机8 小时前
【微实验】组合优化matlab实战(马科维茨投资模型):在收益与风险之间,寻找最优的人生配比
大数据·人工智能·算法·机器学习·数学建模·matlab·组合优化
Nil2089 小时前
leetcode 160相交链表
算法·leetcode·链表
迷途之人不知返10 小时前
算法系列2:滑动窗口
算法
Herbert_hwt10 小时前
C语言零基础入门:循环控制与数据类型详解
c语言·数据结构·算法
Tisfy11 小时前
LeetCode 3090.每个字符最多出现两次的最长子字符串:二重循环 / 滑动窗口
算法·leetcode·字符串·题解·模拟·双指针·滑动窗口
-dzk-11 小时前
【技巧】LC 136.只出现一次的数字
算法·异或
有点。12 小时前
C++二叉树二(练习题)
数据结构·c++·算法·图论
专注仿真12 小时前
问答大模型技术方案算法实现-RAPTOR树构建算法与BEG集成使用
python·算法