LeetCode55-跳跃游戏 | 算法练习系列

181 阅读2分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

好久没写算法题了,今天来一道有意思得算法题,名字叫跳跃游戏,本题得解法大致有三种,从解题效率上大致顺序为递归和贪心,这两钟解题算法中,贪心得效率是最高得,下面我们看下题目

题目描述

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

 

示例 1:

输入:nums = [2,3,1,1,4]

输出:true

解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

输入:nums = [3,2,1,0,4]

输出:false

解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

解题思路

  • 通过题目描述我们可以发现本题得要求是通过数组中项得值来进行跳跃,如果能跳跃到最后得位置或者大于最后得位置都是可以得
  • 其中要注意得一点是假设第一项是5,那么可以移动得步数是1,2,3,4,5,而不是就能移动5步,这点很重要
  • 下面我们首先上一下递归得写法
var canJump = function(nums){ 
    const totalLength = nums.length 
    const dp = Array(totalLength).fill(0) 
    dp[totalLength-1] = 1
    function jump(position) { 
        if(dp[position] === 1){
            return true; 
        }else if(dp[position] === -1){ 
            return false 
        } 
        const maxJump = Math.min(position + nums[position],totalLength -1)
        for(let i=position+1;i<=maxJump;i++){ 
            const jumpResult = jump(i);
            if(jumpResult === true){ 
                dp[position] =1
            return true
            } 
       } 
    dp[position] =-1 
    return false
    } 
    let result=jump(0) 
    return result 
};

解释:首先声明一个和nums长度一样得数组,全部定义为0,通过dp来判断,可以跳到下个的就置为1,否则职位-1,然后递归调用即可,代码逻辑比较复杂,不如下面的贪心算法,下面我们上贪心算法的代码

var canJump = function(nums) {
    let maxJump = nums.length-1;
    for(let i=nums.length-2;i>=0;i--){ 
        if(i+nums[i]>=maxJump){ 
            maxJump=i 
        } 
    } 
    return maxJump === 0 
};

解释:贪心算法的思路是从nums的倒数第二项的下标加上此项的值和到下一项的距离进行比较,如果大于了距离则更新maxJump,如果不大于则接着往前找,直至循环结束,此时如果maxJump的值为0,则说明跳跃成功了,否则就返回false,也就是跳跃失败了

总结

本题中最主要的就是要对每一项的下一步有几个操作要明确,判断每一种操作的情况是否可行,也就是文中提到的每一项的初始状态都设置为0,如果有能走通的路就改为1,否则改为-1