(试讲)LeetCode-45-跳跃游戏 II

示例:

不同于跳跃游戏1只是判断能否到达终点,跳跃游戏II在其基础之上给出了求最小跳跃次数的要求。

那么或许我们会有这样的猜测:我们只要尽可能地往远处跳就可以实现题目的要求。

诚然,这是不错的——

如果我们完全利用了可以远跳的机会,那么显然达到终点所消耗的步数就是最少的。

但是,如果只是单纯地按照这个思路,那么有可能会陷入一个误区

这里先给出按照上述逻辑所实现的错误代码:

class Solution {
    public int Jump(int[] nums){
        if(nums.length <= 1){
            return 0;
        }
        int res = 0;
        int covered = 0;
        for (int i = 0; i < covered; i++) {
            if(covered >= nums.length - 1){
                return res;
            }
            //当发现某一点覆盖范围比当前大就替换当前覆盖范围,并将步数+1
            if(covered < i + nums[i]){
                covered = i + nums[i];
                res++;
            }
        }
        return res;
    }
}

(这里同样利用了跳跃游戏1所用到的覆盖范围的概念)

显然上述代码实现了这样一个功能——当我们在当前覆盖内遇到了任意的一个点,并且这个点使得当前覆盖范围得到增加,那么就更新覆盖范围并且使得跳跃步数加一。

好像没什么问题,我们确实是在往远处跳.....

但这是错误的,上述思维还是仅仅利用了跳跃问题1的思维模式。但是本题与跳跃问题1是有本质差别的。

这里给出上述逻辑错误的原因:

我们没有完全利用到每次跳跃的机会,我们做了步数的浪费!

这样的局部最优是推不出全局最优的!

例如下图:

我们完全可以直接跳到第三个"3"的位置,然后再继续往后跳跃,而不是在途中又经过了第二个"3",这显然是对步数的浪费,也不符合我们确定"覆盖范围"这么一概念的意义。

那么尝试阐明了这么一个可能会出现的错误过后,我们或许可以想到的是——

如果我们遍历完全了当前覆盖范围,并且在当前覆盖范围中找到了接下来可以跳跃的最大覆盖范围的话....是不是就足以推出全局最优了呢?

显然是的,这里先给出具体代码:

class Solution {
    public int jump(int[] nums) {
        int curCover = 0, nextCover = 0;
        int res = 0;
        for (int i = 0; i <= curCover; i++) {
            nextCover = Math.max(nextCover, i + nums[i]);
            //如果nextCover大于了数组长度,那么就不需要循环了
            if(curCover >= nums.length - 1)
                break;
            if(i == curCover){
                res++;
                curCover = nextCover;
            }
        }
        return res;
    }
}

可以看到的是,我们利用了curCover与nextCover

前者表示当前我们所遍历的数组范围,后者表示我们在这个数组范围内所寻得的最大覆盖范围。

当然也是我们下一次所遍历的覆盖范围。

例如,我们假设在xCover中寻得某点x,那么或许在xCover内有许多点都能增大我们的覆盖范围,但是我们的x点,其所能增加的覆盖范围是最多的。所以我们便取x点并记录由其所更新的覆盖范围。也就是——

nextCover = Math.max(nextCover, i + nums[i]);

既然我们已经在当前覆盖范围内取得了下一次遍历最大的覆盖范围,那么何时对当前覆盖范围作更新呢?

显然,我们在遍历到当前覆盖范围末尾时作更新

也就是——

i == curCover

既然对当前覆盖范围做了更新,那么就意味着我们已经利用了一次跳跃机会。

可以这样理解,我们的根本目的就是遍历当前覆盖范围,并且找到能跳跃最远的位置,然后进行跳跃,这也是前文所提到的

但跳跃的过程并没有具体明显地展示,因为其已经包含在了我们的逻辑当中了。

那么照这样下去便能得到我们的全局最优,也就是取得最少跳跃次数了。

这就是我们给出的跳跃游戏II的讲解,当然也有其他算法

这里借鉴了《代码随想录》卡尔老师的思路。卡尔老师的思路确实都很巧妙,其思维逻辑很值得学习,在这里也感谢卡尔老师的讲解!

同样的,给出《代码随想录》本题视频地址,以及其网站——

贪心算法,最少跳几步还得看覆盖范围 | LeetCode: 45.跳跃游戏II_哔哩哔哩_bilibili

代码随想录 (programmercarl.com)

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值