【LeetCode】每日一题 跳跃游戏

69 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情

55. 跳跃游戏

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

「示例1:」
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
「示例2:」
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
「提示:」
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105

解题思路

// 第一种
从后往前判断某一个位置是否能够跳的到最后一个位置。
​
// 第二种
从前往后
​
// 第三种
由题目描述,我们需要达到最后一个下标,那么最后一个下标的数字其实是可以不用考虑的。那么我们可以假设只有两个数字(比如 [2, 4][2,4]),这个时候第一个数字如果是大于等于 11 的数就成立;如果是三个数字的话(比如 [3, 0, 4][3,0,4]),第一个数字大于等于 22 时成立。依此类推,一个数字可以到达的位置必须是这个数字标记的长度值,有:nums[i] >= jnums[i]>=j 成立时才可以到达后面第 jj 个目标。
​
有了上述前提,假设现在只有最后两位数字,在判断出倒数第 22 位数字可以到达最后一位时,我们只需要看剩下的部分,如果可以到达倒数第 22 位,那么整体就可以到达最后一位数字。
​
我们记录一个最后一位的下标,然后依次向前寻找满足跳跃条件的下标,并将该下标与记录的下标替换。重复这个过程直到判断了 numsnums 的第一个下标为止,最后判断记录值是否为第一个下标,也就是 00 ,如果不是 00 返回 falsefalse。该过程时间复杂度为 O(n)O(n),空间复杂度为 O(1)O(1) 。

代码实现

// 第一种
var canJump = function(nums) {
    if (!Array.isArray(nums) || nums.length <= 0) return false;
    let pos = nums.length-1;
    for (let i = nums.length - 2; i >= 0; i--) {
        if (nums[i] + i >= pos) {
            pos = i;
        }
    }
    return pos === 0;
};
​
// 第二种
var canJump = function(nums) {
    if (!Array.isArray(nums) || nums.length <= 0) return false;
    let dp = new Array(nums.length).fill(false);
    dp[0] = true;
    for (let i = 0; i < nums.length; i++) {
        if (dp[i]) {
            for (let j = i; j < nums.length && j <= i + nums[i]; j++) {
                dp[j] = true;
            }
        }
    }
    return dp[nums.length-1];
};
​
// 第三种
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
    // 必须到达end下标的数字
    let end = nums.length - 1;
​
    for (let i = nums.length - 2; i >= 0; i--) {
        if (end - i <= nums[i]) {
            end = i;
        }
    }
​
    return end == 0;
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;