78.跳跃游戏

7 阅读1分钟

题目链接

给你一个非负整数数组 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)