45. 跳跃游戏 II
算法核心
这是一个贪心算法,通过维护当前跳跃边界end和当前可到达的最远位置maxP,每次到达边界时进行跳跃,从而以最小步数到达终点。
关键点
- 遍历到
n-2即可,不需要处理n-1 - 因为题目保证能到达终点
- 在
i=n-2时,要么已经到达终点,要么从n-2能跳到终点 - 处理
n-1会导致多余跳跃计数
两个正常例子证明
例子1:end == n-1(边界正好是终点)
nums = [2, 3, 1, 4, 5],n=5,终点索引=4
索引: 0 1 2 3 4
数值: 2 3 1 4 5
执行过程:
初始: res=0, maxP=0, end=0
i=0: 在位置0,可跳到2
maxP = max(0, 0+2) = 2
i==end(0==0) → 跳跃!
end = 2, res=1
i=1: 在位置1,可跳到4
maxP = max(2, 1+3) = 4
i≠end(1≠2) → 不跳
i=2: 在位置2,可跳到3
maxP = max(4, 2+1) = 4
i==end(2==2) → 跳跃!
end = 4, res=2
★ 此时 end=4 正好等于 n-1
i=3: 循环条件 i<4,i=3<4,继续
maxP = max(4, 3+4) = 7
i≠end(3≠4) → 不跳
循环结束(i=4不会处理)
结果: res=2
分析:
- 在 i=2 时,end=4 已到达终点
- 不需要处理 i=3 和 i=4
- 即使遍历到 n-2=3,也不会再增加跳跃次数
- 终点正好是边界的情况,提前结束没有问题
例子2:end > n-1(边界超过终点)
nums = [3, 2, 1, 1, 1],n=5,终点索引=4
索引: 0 1 2 3 4
数值: 3 2 1 1 1
执行过程:
初始: res=0, maxP=0, end=0
i=0: 在位置0,可跳到3
maxP = max(0, 0+3) = 3
i==end(0==0) → 跳跃!
end = 3, res=1
★ 此时从位置0直接可到终点4(因为3≥4)
i=1: 在位置1,可跳到3
maxP = max(3, 1+2) = 3
i≠end(1≠3) → 不跳
i=2: 在位置2,可跳到3
maxP = max(3, 2+1) = 3
i≠end(2≠3) → 不跳
i=3: 在位置3,可跳到4
maxP = max(3, 3+1) = 4
i==end(3==3) → 跳跃!
end = 4, res=2
★ 实际上这次跳跃是多余的,但算法会计数
结果: res=2
实际最少跳跃 :1次(0→3或0→4)
算法结果 :2次
注意 :这个例子说明算法结果是上界,不一定是最优路径,但题目要求最少跳跃次数,这种情况实际上算法给出了2,但最优是1。
修正例子 :改为 nums = [3, 1, 1, 1, 1]
i=0: end=3, res=1
i=1: maxP=3
i=2: maxP=3
i=3: i==end→end=3, res=2
结果: res=2
边界在3,但可跳到终点
不会出现的例子(理论上存在但题目保证不会出现)
例子3:无法到达终点
nums = [3, 2, 1, 0, 0, 0],n=6
索引: 0 1 2 3 4 5
数值: 3 2 1 0 0 0
执行过程:
初始: res=0, maxP=0, end=0
i=0: 可跳到3
maxP = 3
i==end → end=3, res=1
i=1: 可跳到3
maxP = max(3, 3) = 3
i=2: 可跳到3
maxP = 3
i==end? 2≠3 → 不跳
i=3: 在位置3,nums[3]=0,可跳到3
maxP = 3
i==end(3==3) → 跳跃!
end = 3, res=2
★ 边界没有前进!
i=4: 在位置4,nums[4]=0
maxP = 3
i≠end(4≠3) → 不跳
i=5: 循环条件 i<5,i=4<5,继续
i=5不会处理
结束
问题:
- 在 i=3 时,边界从 3 更新到 3,没有前进
- 之后无法到达终点
- 但题目保证这种情况不会出现
验证能到达终点的条件 :
如果存在某个位置 i 使得 i + nums[i] ≥ n-1,则能到达终点。
在合法输入中,一定存在这样的位置链。
为什么遍历到 n-2 即可:数学证明
定理:
在保证能到达终点的条件下,算法在遍历到 i=n-2 时,maxP ≥ n-1。
证明:
设最后一步跳跃的起点为 k,则 k 满足:
- k ≤ n-2(因为从 n-1 不需要再跳)
- 从 k 可跳到终点:k + nums[k] ≥ n-1
考虑两种情况:
情况A:k < n-2
- 那么在 i=k 时,
maxP ≥ k + nums[k] ≥ n-1 - 此时或之后某个时刻,
end会被更新为 ≥ n-1 - 在 i 到达 n-2 前,
end已 ≥ n-1
情况B:k = n-2
- 在 i=n-2 时,
maxP ≥ (n-2) + nums[n-2] ≥ n-1 - 如果 i=n-2 正好是当前边界,则更新
end ≥ n-1 - 如果 i=n-2 不是当前边界,则之前的
end已 ≥ n-1
因此 :在 i 遍历到 n-2 时,必然有 end ≥ n-1 或即将被设为 ≥ n-1。
重要结论
- 遍历到 n-2 足够:因为终点位置 n-1 不需要作为起跳点
- 避免多余跳跃 :如果在 n-1 处检查
if(i==end),可能会错误增加跳跃次数 - 算法正确性:贪心策略 + 提前终止保证结果正确
- 时间复杂度:O(n),只遍历一次
- 空间复杂度:O(1),只用常数空间
这个算法巧妙地用最小代价解决了问题,是贪心算法的经典应用。