文章目录
-
- 一、题目背景与描述
- 二、问题本质分析
- 三、解法一:贪心算法(推荐)
-
- [1. 核心思想](#1. 核心思想)
- [2. 贪心思维流程图(Mermaid)](#2. 贪心思维流程图(Mermaid))
- [3. 为什么贪心是正确的?](#3. 为什么贪心是正确的?)
- [4. Java 实现代码(贪心)](#4. Java 实现代码(贪心))
- [5. 复杂度分析](#5. 复杂度分析)
- 四、解法二:动态规划(理解用,不推荐)
-
- [1. 核心思想](#1. 核心思想)
- [2. 动态规划状态转移示意图](#2. 动态规划状态转移示意图)
- [3. Java 实现代码(DP)](#3. Java 实现代码(DP))
- [4. 复杂度分析](#4. 复杂度分析)
- [5. 为什么不推荐?](#5. 为什么不推荐?)
- 五、两种解法对比总结
一、题目背景与描述
题目链接:
https://leetcode.cn/problems/jump-game/
题目描述
给定一个非负整数数组 nums,你最初位于数组的第一个下标。
数组中的每个元素代表你在该位置最多可以向前跳跃的步数。
请判断你是否能够到达数组的最后一个下标。
示例说明
示例 1:
text
输入:nums = [2,3,1,1,4]
输出:true
解释:
- 从下标 0 跳 1 步到下标 1
- 从下标 1 跳 3 步到下标 4(终点)
示例 2:
text
输入:nums = [3,2,1,0,4]
输出:false
解释:
- 无论如何都会被卡在下标 3(最大跳跃为 0),无法继续前进
二、问题本质分析
这个问题本质是在问:
在每一步都有限制跳跃长度的情况下,能否通过合理选择跳跃位置,最终覆盖到数组的最后一个下标?
它具有以下特点:
- 不要求最少步数
- 只关心「是否能到达终点」
- 每个位置的选择会影响后续的可达范围
三、解法一:贪心算法(推荐)
1. 核心思想
始终维护当前能到达的最远位置 maxReach
- 从左到右遍历数组
- 每到一个位置
i,如果i > maxReach,说明当前位置无法到达,直接返回false - 否则更新最远可达位置:
text
maxReach = max(maxReach, i + nums[i])
只要在遍历过程中,maxReach 能覆盖到最后一个下标,就说明可以到达终点。
2. 贪心思维流程图(Mermaid)
是
否
是
否
开始:maxReach = 0
遍历数组 i 从 0 到 n-1
i > maxReach ?
返回 false
更新 maxReach = max(maxReach, i + nums[i])
maxReach >= n-1 ?
返回 true
3. 为什么贪心是正确的?
- 我们并不关心"从哪里跳",只关心"最远能跳到哪里"
- 每一步选择当前能跳得最远的位置,一定不会比其他选择更差
- 一旦出现某个位置不可达,后面的所有位置都不可达
4. Java 实现代码(贪心)
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;
}
}
5. 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |
四、解法二:动态规划(理解用,不推荐)
1. 核心思想
定义一个布尔数组:
text
dp[i] 表示:是否能够跳到位置 i
状态转移:
text
dp[i] = 存在某个 j < i,使得 dp[j] == true 且 j + nums[j] >= i
2. 动态规划状态转移示意图
0
1
2
3
4
只要某个位置可以由前面任意一个可达位置跳到,就标记为 true。
3. Java 实现代码(DP)
java
class Solution {
public boolean canJump(int[] nums) {
int n = nums.length;
boolean[] dp = new boolean[n];
dp[0] = true;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && j + nums[j] >= i) {
dp[i] = true;
break;
}
}
}
return dp[n - 1];
}
}
4. 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间复杂度 | O(n²) |
| 空间复杂度 | O(n) |
5. 为什么不推荐?
- 数据规模大时容易超时
- 贪心算法能用更低的复杂度解决同样问题
五、两种解法对比总结
Jump Game
贪心算法
思路简单
一次遍历
O(n) 时间
面试首选
动态规划
思路直观
状态转移清晰
O(n²) 时间
不适合大规模
- 不要纠结"怎么跳",只关注"能跳多远"
- 一旦当前位置超过最远可达范围,直接失败
- 贪心是该题的最优解法