LeetCode 55中等贪心
跳跃游戏 图解题解
这道题到底在问什么
每个格子的数字是在这一格最多能往右跳几步,从 0 号位出发,问能否到达最后一格。
- nums
- [2, 3, 1, 1, 4]
- 输出
- true
先想最直接的笨办法
在每一格都枚举「跳 1 步、跳 2 步…」一路递归试到底,路径会指数爆炸,还会反复算同一格能不能到终点。其实根本不必关心怎么跳。(动画第 3 步)
最优解:一步一步想明白
- 3在每一格都枚举「跳 1 步、跳 2 步…」一路递归试到底,路径会指数爆炸,还会反复算同一格能不能到终点。其实根本不必关心怎么跳。
- 4转折:从左往右扫,只要一个格子在 maxReach 范围内能站住,它能到的地方我就也能到。所以每到一格就用
maxReach = max(maxReach, i + nums[i])把边界往外推。一旦 maxReach 盖过终点就成;要是走到某格时 i 已经超出 maxReach,说明这格根本站不上去,卡死返回 false。贪心成立的关键:能到的范围是连续的一段,维护它的右边界就行。 - 5maxReach = 2站在 0 号位能跳 2 步,最远摸到 2 号位。橙色区间就是当前你够得着的范围 [0, 2]。
- 6maxReach = 41 号位在可达范围内(1 ≤ 2),站得上去。它能跳 3 步到 4 号位,maxReach 被推到 4——已经盖住终点了,但我们把扫描走完看看每步怎么动。
- 7maxReach 仍 = 42 号位也在范围内。它只能跳 1 步到 3 号位,比现有的 4 近,maxReach 不更新,仍是 4。
- 8maxReach 仍 = 43 号位还在范围内,它能到的 4 号位也没超过现有边界。maxReach 保持 4。
- 9maxReach 4 ≥ 终点 4走到最后一格 4,它本身就在可达范围内(4 ≤ maxReach=4)。能到达,返回 true。
- 10maxReach = 3换个会失败的数组 [3,2,1,0,4]。0 号位跳 3 步,maxReach=3,范围 [0,3]——终点 4 还差一格够不到。
- 11maxReach 仍 = 31 号位在范围内,它能到 1+2=3,没超过现有边界,maxReach 不动,还是 3。范围卡在 [0,3] 里推不出去。
- 120 号挡路 → maxReach 停 3一路走到 3 号位,它的值是 0,3+0 还是 3,maxReach 推不动了。下一步 i=4 时 4 > maxReach=3,站不上去 → 返回 false。一个 0 卡在关键位置就能堵死整条路。
- 15不纠结具体怎么跳、跳几次,只维护全局的「可达右边界」maxReach,让它一路向外推——这就是可达性贪心。
- 20把这题练到能复述后,再去同类题里迁移:先复用状态定义,再调整边界条件。
⚠️ 容易写错的地方
✗ 错:不判断 i > maxReach 就继续更新
✓ 对:循环里先 if i > maxReach: return False
像 [3,2,1,0,4],不判断的话会去「更新」一个根本站不上的格子,得出错误的 true
✗ 错:把 nums[i] 当成「跳到哪个下标」
✓ 对:最远位置是 i + nums[i]
nums[i] 是步数不是目标下标,忘了加当前下标 i 边界全算错
完整代码(Python / C++ / Java)
Python
class Solution:
def canJump(self, nums):
maxReach = 0
for i, jump in enumerate(nums):
if i > maxReach:
return False
maxReach = max(maxReach, i + jump)
return TrueC++
class Solution {
public:
bool canJump(vector<int>& nums) {
int maxReach = 0;
for (int i = 0; i < (int)nums.size(); i++) {
if (i > maxReach) return false;
maxReach = max(maxReach, i + nums[i]);
}
return true;
}
};Java
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]);
}
return true;
}
}套路模板 · 可达边界贪心骨架
# 可达边界贪心 骨架
maxReach = 0
for i, x in enumerate(nums):
if i > maxReach: # 当前下标已超出能到的最远 → 卡死
return False
maxReach = max(maxReach, i + x)
if maxReach >= len(nums) - 1: # 已能盖住终点,提前结束
return True
return True复杂度
时间复杂度
O(n)
只从左到右扫一遍,每格做常数次比较
空间复杂度
O(1)
只用 maxReach 一个变量,不存路径
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 跳跃游戏 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
为什么维护「最远可达」就够?+
只要末尾在最远可达内就能到;过程中若某位置超出当前最远可达,说明断了、必到不了。
和「跳跃游戏 II(最少步数)」区别?+
本题只判能否到;II 求最少步数,要在每段可达范围内贪心选下一跳的最远落点。
复杂度?+
O(n) 一次遍历、O(1) 空间。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。