跳转至

45. 跳跃游戏 II

LeetCode 451 · 中等 · 贪心算法

题

数组 nums 里每个数是在该位置最多能往前跳几步,从下标 0 出发,保证能到最后一个下标,求最少跳几次。

例:nums = [2, 3, 1, 1, 4] → 2(0 → 1 → 4)。

一句话

k 跳能到的位置是一段连续区间;扫到当前区间的右边界 end 时,必须再跳一次,新边界是区间内所有位置能到的最远处 far。

关键技巧

把 BFS 的「层」压成区间。 从 0 出发做 BFS,第 k 层就是恰好 k 跳首次到达的位置。由 55. 跳跃游戏 的结论,可达集合总是前缀,所以每一层是一段连续区间 [start, end]——不用队列,两个指针就能表示一层。

层内扫描求下一层边界。 扫第 k 层时,用 far = max(far, i + nums[i]) 记录下一层的右端;i 走到 end 就「出层」:jumps += 1,end = far。

为什么贪心不亏。 它就是 BFS,BFS 按层扩展天然给出最短步数;「贪心」只体现在不去关心具体跳到层里哪个点——层内任何点都只花 k 跳,谁能跳得最远就让谁定义下一层。

循环只到 n - 2。 站在最后一格不需要再跳;若扫到 n - 1,恰好 i == end 时会多算一跳。

解

class Solution:
    def jump(self, nums: List[int]) -> int:
        jumps = end = far = 0
        for i in range(len(nums) - 1):  # 终点不用再起跳
            far = max(far, i + nums[i])
            if i == end:                # 当前层扫完,必须再跳一次
                jumps += 1
                end = far
        return jumps

时间 \(O(n)\),空间 \(O(1)\)。

延伸

自测
s = Solution()
assert s.jump([2, 3, 1, 1, 4]) == 2
assert s.jump([2, 3, 0, 1, 4]) == 2
assert s.jump([0]) == 0
assert s.jump([1, 1, 1, 1]) == 3

  1. LeetCode 45,2026-09-29 读。 ↩