⭐算法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 ] dp[i]=max(dp[j]+nums[i])其中j∈[i−k,i−1] dp[i]=max(dp[j]+nums[i])其中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),适用于较大的输入规模。
相关推荐
czy878747516 分钟前
两种常见的C语言实现64位无符号整数乘以64位无符号整数的实现方法
c语言·算法
yzx99101332 分钟前
支持向量机案例
算法·机器学习·支持向量机
狐凄38 分钟前
Python实例题:pygame开发打飞机游戏
python·游戏·pygame
天上路人43 分钟前
采用AI神经网络降噪算法的语言降噪消回音处理芯片NR2049-P
深度学习·神经网络·算法·硬件架构·音视频·实时音视频·可用性测试
chao_7891 小时前
手撕算法(定制整理版2)
笔记·算法
AndrewHZ3 小时前
【图像处理基石】什么是油画感?
图像处理·人工智能·算法·图像压缩·视频处理·超分辨率·去噪算法
.格子衫.3 小时前
015枚举之滑动窗口——算法备赛
数据结构·算法
J先生x4 小时前
【IP101】图像处理进阶:从直方图均衡化到伽马变换,全面掌握图像增强技术
图像处理·人工智能·学习·算法·计算机视觉
爱coding的橙子6 小时前
每日算法刷题 Day3 5.11:leetcode数组2道题,用时1h(有点慢)
算法·leetcode
?abc!11 小时前
缓存(5):常见 缓存数据淘汰算法/缓存清空策略
java·算法·缓存