(LeetCode-Hot100)55. 跳跃游戏

问题简介

🔗 LeetCode 55. 跳跃游戏

题目描述

给定一个非负整数数组 nums,你最初位于数组的第一个下标。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。


示例说明

✅ 示例 1:

text 复制代码
输入: nums = [2,3,1,1,4]
输出: true
解释: 从下标 0 跳 1 步到下标 1,然后跳 3 步到达最后一个下标。

✅ 示例 2:

text 复制代码
输入: nums = [3,2,1,0,4]
输出: false
解释: 无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0,所以永远不可能到达最后一个下标。

解题思路

📌 核心思想 :我们不需要知道具体怎么跳,只需要判断能否到达终点。因此,可以维护一个变量表示当前能到达的最远位置。


✅ 方法一:贪心算法(推荐)

步骤如下:

  1. 初始化 maxReach = 0,表示当前能到达的最远下标。
  2. 遍历数组(只需遍历到倒数第二个元素,因为最后一步不需要再跳):
    • 如果当前下标 i > maxReach,说明无法到达当前位置,直接返回 false。
    • 否则,更新 maxReach = max(maxReach, i + nums[i])。
  3. 遍历结束后,若 maxReach >= n - 1,则可以到达终点。

💡 为什么有效?

因为我们始终记录"能到达的最远位置",只要这个位置 ≥ 最后一个下标,就说明可达。


❌ 方法二:动态规划(不推荐,仅作对比)
  • 定义 dp[i] 表示是否能到达下标 i。
  • 初始 dp[0] = true。
  • 对每个 i,若 dp[i] == true,则将 i+1 到 i+nums[i] 的位置都设为 true。
  • 最终返回 dp[n-1]。

⚠️ 缺点:时间复杂度 O(n²),在 LeetCode 上会超时或效率低。


✅ 方法三:反向遍历(另一种贪心)
  • 从后往前找,维护一个 lastPos = n - 1(目标位置)。
  • 若 i + nums[i] >= lastPos,说明从 i 可以跳到 lastPos,更新 lastPos = i。
  • 最终若 lastPos == 0,说明可以从起点跳到终点。

💡 这种方法逻辑清晰,但实际效率略低于正向贪心(因需完整遍历)。


代码实现

java 复制代码
// Java 实现 - 贪心(正向)
class Solution {
    public boolean canJump(int[] nums) {
        int maxReach = 0;
        int n = nums.length;
        
        for (int i = 0; i < n; i++) {
            if (i > maxReach) {
                return false;
            }
            maxReach = Math.max(maxReach, i + nums[i]);
            // 提前终止优化
            if (maxReach >= n - 1) {
                return true;
            }
        }
        return true;
    }
}
go 复制代码
// Go 实现 - 贪心(正向)
func canJump(nums []int) bool {
    maxReach := 0
    n := len(nums)
    
    for i := 0; i < n; i++ {
        if i > maxReach {
            return false
        }
        if i + nums[i] > maxReach {
            maxReach = i + nums[i]
        }
        // 提前终止
        if maxReach >= n - 1 {
            return true
        }
    }
    return true
}

💡 提示 :以上代码均采用正向贪心,并加入提前终止优化,效率最高。


示例演示

以 nums = [2,3,1,1,4] 为例:

i numsi maxReach(更新前) 是否 i > maxReach? 更新后 maxReach
0 2 0 否 max(0, 0+2)=2
1 3 2 否 max(2, 1+3)=4
2 1 4 否 4(不变)
... ... ... ... ...

✅ 在 i=1 时,maxReach = 4 >= 4(n-1),提前返回 true。


答案有效性证明

📌 贪心选择性质 :

在每一步,我们都选择"能跳得最远"的策略,这不会导致错过可行解。因为如果存在一条路径能到达终点,那么必然存在某个时刻,我们的 maxReach 能覆盖终点。

📌 最优子结构 :

能否到达位置 i,只依赖于前面所有位置中能跳到 i 的最大能力。因此局部最优(最远可达)可推出全局最优(能否到终点)。

✅ 因此,贪心算法在此问题中是正确且完备的。


复杂度分析

方法 时间复杂度 空间复杂度 说明
贪心(正向) O(n) O(1) 一次遍历,常数空间
动态规划 O(n²) O(n) 每个位置可能更新多个状态
贪心(反向) O(n) O(1) 一次反向遍历

✅ 推荐使用正向贪心,简洁高效。


问题总结

  • 🔑 关键洞察:无需关心具体跳跃路径,只需关注"最远能到哪"。
  • 🧠 思维转变:从"如何跳" → "能不能到",简化问题。
  • ⚡ 技巧 :提前终止(一旦 maxReach >= n-1 就返回)可提升性能。
  • 📌 适用场景:此类"可达性"问题常可用贪心解决,尤其是当"局部最优能保证全局最优"时。

💡 延伸思考 :本题变种 LeetCode 45. 跳跃游戏 II 要求最少跳跃次数,同样可用贪心解决,但需记录"跳跃次数"和"当前边界"。

github地址: https://github.com/swf2020/LeetCode-Hot100-Solutions

相关推荐
马剑威(威哥爱编程)3 小时前
【AI全栈后端12-02】Spring Boot 跑通第一个 AI 对话接口:HR 政策问答机器人实战
java·人工智能·spring boot·机器人
55873生态系统手记3 小时前
读完 55873 资产钱包的技术栈,我重新理解了 "合规钱包" 应该长什么样
算法·架构
IT枫斗者枫哥3 小时前
AI返回合法JSON,字段就可信吗?给抽取结果补一道业务校验
java·人工智能·后端
旋生万物3 小时前
素数螺旋映射 $z_n=n^{1+i}$ 的角分布统计检验与零模型对比
大数据·前端·人工智能·算法·云原生·螺旋生成论·螺旋相位
HRTOS3 小时前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机
天天被压力3 小时前
【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #06】Python实时行情总报错?五档盘口+逐笔一次跑通
java·人工智能·python
今年下半年3 小时前
【网站连通性检测】java项目telnet、curl命令的使用
java·curl·telnet
摇滚侠3 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC 容器的高级机制 编程式驱动 IOC 阅读笔记 7
java·spring boot·笔记
IT枫斗者枫哥3 小时前
ORDER BY时间还会漏单?用相同时间和插入记录测一次分页
java·后端
IT枫斗者枫哥3 小时前
UPDATE影响0行,接口却返回成功:把版本冲突接回业务
java·后端