给你一个非负整数数组
nums
,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回
true
;否则,返回false
。
解法1 记忆化搜索(暴力dfs优化版)
思路
刚开始想的是暴力解法,就是从每个索引上开始向后遍历,其中 nextPosition
是当前索引上的值能够走到的最远距离,如果走到了数组队尾,那么说明可以到达。
如果不经过缓存优化,这样的时间复杂度太高是过不了用例的。所以下面用 memo
来缓存当前索引上的情况,如果等于 1
说明可以到达,如果为 -1
说明已经走过。
代码
function canJump(nums: number[]): boolean {
const len = nums.length;
const memo = new Array(len).fill(0);
memo[len - 1] = 1;
const dfs = (position) => {
if (memo[position] !== 0) return memo[position] === 1;
const nextPosition = Math.min(position + nums[position], len - 1);
for (let next = position + 1; next <= nextPosition; next++) {
if (dfs(next)) {
memo[position] = 1;
return true;
}
}
memo[position] = -1;
return false;
};
return dfs(0);
};
时空复杂度
时间复杂度:O(n^2)
空间复杂度:O(n)
解法2 贪心
思路
我们从右往左遍历,只记录当前能够到达终点的最左位置。如果某个位置可以跳到这个位置,那么它也能跳到终点。(我想不出来)
代码
function canJump(nums: number[]): boolean {
const n = nums.length;
let lastGoodPos = n - 1;
for (let i = n - 2; i >= 0; i--) {
if (i + nums[i] >= lastGoodPos) {
lastGoodPos = i;
}
}
return lastGoodPos === 0;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(1)