给定一个长度为
n的0索引整数数组nums。初始位置为nums[0]。每个元素
nums[i]表示从索引i向后跳转的最大长度。换句话说,如果你在nums[i]处,你可以跳转到任意nums[i + j]处:
0 <= j <= nums[i]
i + j < n返回到达
nums[n - 1]的最小跳跃次数。生成的测试用例可以到达nums[n - 1]。
解法1 动态规划
思路
从右往左推,每个位置存储的是从当前位置跳到终点的最小跳跃数;每次尝试所有能跳到的位置,取其中最小的跳跃数 + 1。
代码
function jump(nums: number[]): number {
const n = nums.length;
const dp = new Array(n).fill(Infinity);
dp[n - 1] = 0;
for (let i = n - 2; i >= 0; i--) {
const maxJump = Math.min(i + nums[i], n - 1);
for (let j = i + 1; j <= maxJump; j++) {
dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
return dp[0];
};
时空复杂度
时间复杂度:O(n^2)
空间复杂度:O(n)
解法2 贪心
思路
整题的核心思路就是每次在可达范围内跳得最远,尽可能少跳。
维护三个变量:
-
jumps:跳跃次数; -
currentEnd:当前跳跃能到达的最远边界; -
farthest:下一次跳跃能到达的最远位置。
每次走到 currentEnd,就意味着必须跳一次了。
代码
function jump(nums: number[]): number {
let jumps = 0;
let farthest = 0;
let currentEnd = 0;
for (let i = 0; i < nums.length - 1; i++) {
farthest = Math.max(farthest, i + nums[i]);
if (i === currentEnd) {
jumps++;
currentEnd = farthest;
}
}
return jumps;
}
时空复杂度
时间复杂度:O(n)
空间复杂度:O(1)