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

LeetCode 每日一题笔记

0. 前言

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

1. 题目理解

问题描述 :

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

  • 从下标 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) 暴力遍历,效率大幅提升。
  • 本质:用区间标记代替逐个标记,是跳跃游戏的经典优化思路。
相关推荐
Pniubi6 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
一壶浊酒伴余生10 小时前
新概念英语第一册 · 句法笔记
笔记·英语学习·英语语法·新概念英语
蒸蒸yyyyzwd13 小时前
后端学习笔记 day111
笔记·学习
叼烟扛炮14 小时前
[LangChain] 学习笔记(08):工具调用底层闭环与第三方搜索(Tavily)实战
人工智能·笔记·学习·langchain
江屿风15 小时前
【Git-组件】【Git入门:从文档灾难到版本掌控】流食般投喂
运维·笔记·git·组件·版本控制
小李不想当小白16 小时前
HAL库之UART(STM32 HAL库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
旖旎夜光17 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
Rain的Java大神之路17 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
旖旎夜光18 小时前
【C++ 基础入门】C++多态(下):单/多继承虚表、多态补充与 21 道高频题
开发语言·c++·笔记·学习
Pniubi18 小时前
力扣73 矩阵置零
算法·leetcode·矩阵