贪心热门问题4:跳跃游戏

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心热门问题4:跳跃游戏相关的知识,希望对你有一定的参考价值。

贪心的问题没有固定的套路,那该怎么应对呢?方法很简单,常考的题目是有限的,将常见的贪心问题都做一遍就行了,这样遇到新问题,也大致知道该怎么处理。很多算法的示例序列都不会变,直接考察,因为一旦改变,意义可能就变了。如果要说贪心考察哪个问题最多,这个跳跃游戏一定名列靠前。先看一下题目要求:

leetCode 55 给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。

示例1:

输入: [2,3,1,1,4]
输出: true
解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。

示例2:

输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。

当前位置元素如果是3,我究竟是跳一步呢,还是两步呢,还是三步呢,究竟跳几步才是最优呢?如果不能枚举,你可能想到了回溯,其实用回溯也能画出图来,只要最后一层能够到4就行,但是具体处理起来略有麻烦, 我们还是用贪心思路来做吧。

这里的关键是怎么判断能否到达终点。这里其实不用考虑每一步跳跃到那个位置,而是尽可能的跳跃到最远的位置,看最多能覆盖的位置,不断更新能覆盖的距离,只要能覆盖到就行了。

例如上面的第一个例子,3能覆盖的范围是后面的2,1,0,所以只要接下来2能覆盖后面的1,0,而1只能覆盖到0,所以无法到达4。

而第二个例子,2能覆盖3,1,3可以覆盖后面的1,1,4,已经找到一条路了。

1只能到下一个1,下一个1能到4,所以这里有2,1,1,4和2,3,1,1,4两种走法。

所以加起来有3种跳法。理解到这里我们就可以写代码了,都不用管什么是贪心。如果非要用贪心来解释一嘴,那就是贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。

i每次移动只能在cover的范围内移动,每移动一个元素,cover得到该元素数值(新的覆盖范围)的补充,让i继续移动下去。而cover每次只取 max(该元素数值补充后的范围, cover本身范围)。如果cover大于等于了终点下标,直接return true就可以了。

class Solution 
    public boolean canJump(int[] nums) 
        if (nums.length == 1) 
            return true;
        
        //覆盖范围, 初始覆盖范围应该是0,因为下面的迭代是从下标0开始的
        int cover = 0;
        //在覆盖范围内更新最大的覆盖范围
        for (int i = 0; i <= cover; i++) 
            cover = Math.max(cover, i + nums[i]);
            if (cover >= nums.length - 1) 
                return true;
            
        
        return false;
    

这道题目的难点是要想到覆盖范围,而不用拘泥于每次究竟跳跳几步,覆盖范围是可以逐步扩展的,只有能覆盖就一定是可以跳过来的,不用管是怎么跳的。

再进一步,如果这里再让你考虑用最少的步数该怎么办呢?上面的例子我们可以 看到,有三种走法2,3,4、2,1,1,4和2,3,1,1,4,那这时候改怎么办呢?这个也能用贪心来解决,这个题目就是LeetCode45的要求,感兴趣的可以研究一下。

以上是关于贪心热门问题4:跳跃游戏的主要内容,如果未能解决你的问题,请参考以下文章

55. 跳跃游戏-贪心-中等难度

贪心算法:跳跃游戏

如何用DP和贪心算法玩跳跃游戏?

贪心算法:跳跃游戏II

力扣Leetcode 45. 跳跃游戏 II - 贪心思想

Leetcode 055. 跳跃游戏 贪心