题目描述

✅ 55. 跳跃游戏

image-20260928195015745

题意分析

从下标 0 出发,nums[i] 表示在位置 i 最多能向右跳多少步,可以选择不超过这个上限的步数,不要求每次都跳满。判断是否存在一条路线到达最后一个下标,返回布尔值。

数组非空,元素均为非负数;零表示不能从该位置继续向右跳,但可以从更早的位置越过它。只要求判断可达性,不需要给出路线或最少跳数;只有一个元素时,起点已经是终点。

解法:贪心维护最远可达下标

核心思路

[!blue]

从一个可达位置出发,可以选择任意不超过上限的跳跃长度,因此能新增的是一整段连续位置。起点天然可达,每次扩张又与已有可达区间相接,所以可达位置始终构成从 0 开始的连续前缀,只记录最远边界 maxReach 就足够。

从左向右考察 i。若 i <= maxReach,说明之前已经找到某条路线到达这里,于是可以继续跳到最远的 i + nums[i],用它与旧边界取最大值。这里是在合并所有可达路线的能力,并不是要求实际路线逐个经过这些下标。

若 i > maxReach,此前所有可达位置的跳跃能力都已经检查,却仍无法到达 i。任何更右的位置也无法越过这段缺口,不能拿它们的数值来扩张边界,所以可以直接返回失败。

一旦 maxReach >= n - 1 就能返回成功。即使某次跳跃的最大落点越过终点,也可以少跳几步恰好到达末尾。整个过程只需把已可达位置的能力合并到一个不回退的右边界,无需枚举路线。

解题步骤

  1. 初始化 maxReach = 0,表示起点天然可达。
  2. 从左到右遍历下标 i;若 i > maxReach,当前位置不可达,返回 false。
  3. 当前位置可达时,用 maxReach = max(maxReach, i + nums[i]) 扩展最远边界。
  4. 若边界已经覆盖 n - 1,提前返回 true。

代码实现

class Solution {
    public boolean canJump(int[] nums) {
        int maxReach = 0;

        for (int i = 0; i < nums.length; i++) {
            // 先确认当前位置可达,不能让缺口后的值参与扩展。
            if (i > maxReach) {
                return false;
            }

            // 保留已有最远边界,较短的新跳跃不能让边界倒退。
            maxReach = Math.max(maxReach, i + nums[i]);

            if (maxReach >= nums.length - 1) {
                return true;
            }
        }

        return true;
    }
}
func canJump(nums []int) bool {
    maxReach := 0
    for i := 0; i < len(nums); i++ {
        // 先确认当前位置可达,不能让缺口后的值参与扩展。
        if i > maxReach {
            return false
        }

        reach := i + nums[i]
        // 保留已有最远边界,较短的新跳跃不能让边界倒退。
        if reach > maxReach {
            maxReach = reach
        }
        if maxReach >= len(nums)-1 {
            return true
        }
    }
    return true
}

复杂度分析

  • 时间复杂度:$O(n)$,每个下标最多访问一次。
  • 空间复杂度:$O(1)$,只维护最远可达边界。

关键点总结

[!green]

  • 可达集合是连续前缀,因此一维边界足以替代整张 DP 表。
  • 更新顺序必须是“先确认当前位置可达,再用它扩展边界”。
  • 本题只问可达性;若追问最少跳数,需要像 45 题那样额外维护当前跳跃边界并分层计步。

易错点总结

[!yellow]

  • 必须先判断 i > maxReach,不可达位置即使存着很大的跳跃长度,也不能帮助越过缺口。
  • 不能见到零就失败,之前的跳跃可能已经覆盖它后面的位置;是否失败取决于可达边界。
  • 不可达条件是 i > maxReach,不是 i >= maxReach;边界位置本身仍然可达。
  • 更新要取最大值,不能直接赋值为 i + nums[i],否则较弱的后续位置可能让边界倒退。
  • 单元素数组的起点就是终点,即使该元素为零,也应返回 true。

相似题目

题目 难度 关联与区别
45. 跳跃游戏 II 中等 可达右边界的维护相同,原题还按边界扩张的轮次统计最少跳跃次数。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/26308309
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!