LeetCode 每日一题笔记 日期:2026.05.25 题目:1871. 跳跃游戏 VII

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.05.25
  • 题目:1871. 跳跃游戏 VII
  • 难度:中等
  • 标签:动态规划、前缀和、差分数组

1. 题目理解

问题描述

给定一个下标从 0 开始的二进制字符串 s 和两个整数 minJumpmaxJump

  • 从下标 0 出发
  • 在下标 i 处,可以跳跃到 [i + minJump, i + maxJump] 范围内
  • 只能落在值为 '0' 的下标上
    判断能否到达最后一个下标。

示例

输入:s = "011010", minJump = 2, maxJump = 3

输出:true

2. 解题思路

核心观察

  • 每个位置 i 能否到达,取决于区间 [i-maxJump, i-minJump] 内是否有可达位置。
  • 前缀和 快速查询区间内可达位置数量,用差分数组快速标记可达区间。

算法步骤

  1. 初始化可达标记与前缀和/差分数组。
  2. 遍历每个位置,判断是否能从前面的位置跳过来。
  3. 用前缀和快速查询区间和,用差分数组批量更新可达区间。
  4. 最后一位是否可达即为答案。

3. 代码实现

java 复制代码
package lc1871;

import java.util.Arrays;

public class Solution {
    public boolean canReach(String s, int minJump, int maxJump) {
        int n = s.length();
        boolean[] dp = new boolean[n];
        dp[0] = true;
        int[] pre = new int[n + 1];
        pre[1] = 1;

        for (int i = 1; i < n; i++) {

            int L = Math.max(0, i - maxJump);
            int R = i - minJump;

            if (R < 0) {
                dp[i] = false;
            } else {
                if (pre[R + 1] - pre[L] > 0 && s.charAt(i) == '0') {
                    dp[i] = true;
                } else {
                    dp[i] = false;
                }
            }
            pre[i + 1] = pre[i] + (dp[i] ? 1 : 0);
        }
        return dp[n - 1];
    }
}

4. 代码优化说明

java 复制代码
class Solution {
public boolean canReach(String s, int minJump, int maxJump) {
    // 转为字符数组,提高访问效率
    char ch[]=s.toCharArray();
    int n=ch.length;
    // 差分数组,用于区间更新可达标记
    int diff[]=new int[n];
    // 当前区间内可达位置的数量
    int sum=0;
    
    // 终点是1,直接不可能到达
    if(ch[n-1]=='1'){
        return false;
    }
    
    // 初始化差分数组:0位置可达,区间[0,0] +1
    diff[0]=1;
    diff[1]=-1;
    
    for(int i=0;i<n;i++){
        // 计算当前位置的可达状态(前缀和)
        sum+=diff[i];
        // 当前位置不可达,直接跳过
        if(sum<=0){
            continue;
        }
        // 当前位置是0,可以跳跃
        if(ch[i]=='0'){
            // 计算能跳到的左右边界
            int start=i+minJump;
            int end=Math.min(i+maxJump,n-1);
            
            // 区间无效,跳过
            if(start>end){
                continue;
            }
            // 直接跳到终点,返回true
            if(end==n-1){
                return true;
            }
            // 差分数组区间更新:[start,end] +1
            diff[start]+=1;
            diff[end+1]-=1;
        }
    }
    // 遍历结束未到达终点
    return false;
}
}

5. 复杂度分析

  • 时间复杂度 :O(n)O(n)O(n)
    一次遍历 + 差分数组 O(1)O(1)O(1) 区间更新。
  • 空间复杂度 :O(n)O(n)O(n)
    差分数组空间开销。

6. 总结

  • 核心:差分数组 + 前缀和 优化跳跃区间的可达性更新。
  • 优势:避免 O(n2)O(n^2)O(n2) 暴力遍历,效率大幅提升。
  • 本质:用区间标记代替逐个标记,是跳跃游戏的经典优化思路。
相关推荐
云边有个稻草人2 小时前
2026远程游戏横测,暑假用手机接管电脑,ToDesk VS 向日葵怎么选?
游戏·智能手机·电脑
2501_9364156911 小时前
可变参数&综合练习&斗地主游戏
java·windows·游戏
FellAveal12 小时前
【Go语言入门学习笔记】Part18.工作池与WaitGroup(也即协程池)
笔记·学习·golang
xqqxqxxq13 小时前
Java Socket 多人聊天室(私聊+群聊)技术笔记(V4版本)
java·网络·笔记
龙仔72513 小时前
人大金仓OS_Core数据库自动备份实施笔记(银河麒麟Linux)
linux·数据库·笔记·备份·人大金仓
小poop14 小时前
轮转数组:从暴力到最优,一题掌握算法复杂度分析
数据结构·算法·leetcode
笨鸟先飞的橘猫14 小时前
只会脚本语言的游戏后端自我提升之路——c++学习(开篇)
学习·游戏
Z59981784115 小时前
c#软件开发学习笔记--Modbus-RTU通讯
笔记·学习·c#
quanjui16 小时前
【医学尝试】基于Segment Anything Model的医学图像分割研究:眼底OCT与X线胸片微调实战
人工智能·笔记·学习
小黄蚁16 小时前
FreeRTOS学习笔记(十二)
笔记·学习