跳跃游戏
能否到达终点怎么用 dp 表示?
- 问题: 每个位置的值是最大跳跃长度, 判断能否从
0跳到末尾 (55); - 状态:
dp[i]为从位置0出发能跳出的最远距离; - 转移:
- 若
dp[i-1] >= i, 说明能到达位置i, 可以起跳:dp[i] = max(dp[i-1], i + nums[i]); - 否则位置
i不可达, 最远距离不变:dp[i] = dp[i-1];
- 若
- 初值:
dp[0] = nums[0]; - 答案:
dp[n-1] >= n-1;
const canJump = (nums) => {
const n = nums.length;
const dp = new Array(n).fill(0);
dp[0] = nums[0];
for (let i = 1; i < n; i++) {
dp[i] = dp[i - 1] >= i ? Math.max(dp[i - 1], nums[i] + i) : dp[i - 1];
}
return dp[n - 1] >= n - 1;
};
- 优化: 只需维护一个"当前最远可达位置"变量, 时间从
O(n)状态变为原地滚动, 空间O(1);
最少步数怎么用 dp 表示?
- 问题: 求跳到末尾的最少跳跃次数 (45);
- 状态:
dp[i]为从0到位置i的最少步骤; - 转移: 枚举所有能跳到
i的位置j, 取最小步骤加一;- 条件:
j + nums[j] >= i; - 方程:
dp[i] = min(dp[i], dp[j] + 1);
- 条件:
- 初值:
dp全部填Infinity,dp[0] = 0; - 答案:
dp[n-1]; - 复杂度: 时间
O(n^2), 空间O(n);
const jump = (nums) => {
const n = nums.length;
const dp = new Array(n).fill(Infinity);
dp[0] = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < i; j++) {
if (j + nums[j] >= i) dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
return dp[n - 1];
};