LeetCode 45. Jump Game II (贪心)

题目描述:

每个点的数字代表可以从当前节点跳跃最远的节点数,比如 [ 2, 3, 1, 1, 4 ] 第一个节点跳跃最远位置就是下标为2的第三个元素。

求跳到最后一个节点最少需要跳跃多少次?

解析:

说实话,这题长得就像一个典型的动归,甚至忍不住往动归想。但是俗话说嘛,能用简单的方法解决就用简单的方法解决,所以尝试一下贪心,不过试一下确实是有戏。

对吧,首先要用贪心算法先要把定义搬上来:在对问题求解时,总是做出在当前看来是最好的选择。

那么我们先对当前状况选择,就拿题目的示例: [ 2, 3, 1, 1, 4 ]

最开始的子任务,第一个元素肯定不用考虑了,直接为0,[2],一开始就在第一个位置上不用跳。

第二个位置,[ 2, 3 ],那么跳法肯定是 index:0 -> index:1

第三个位置,[ 2, 3, 1 ],对于第三个元素,上一跳可以是第一个元素,可以是第二个元素,那么就是一个选择的问题了,贪心算法告诉我们要选现在看起来最好的,原本覆盖范围内越远越好:

那其实很好选,第三个元素在第一个元素的覆盖范围内,所以选上面那种是最好的。

所以得出第一个思路:在上次选择节点的覆盖范围内,我们不需要进行多余的跳跃(如上面例子,第一个元素2是上次选择节点,对于第三个元素不需要多余的跳跃从2 -> 3 -> 1)

第一个思路提供了覆盖得到的情况下的最好选择,那么问题又来了,如果覆盖不到了咋整,那就必须进行跳跃,那么问题又来了,跳跃从上个节点跳到哪个节点上?当前节点?还是上次节点到当前节点的某个节点上?

解决这几个问题基本就可以收工了,当我们必须要跳跃的情况下,贪心算法说:我们要选现在看起来最好的,很明显覆盖范围越远越好,那么就很好选了,选上次节点到当前节点之间覆盖最远那个节点,说的有些抽象,可以看图:

那么两个思路就出来了:

1. 在上次选择节点的覆盖范围内,我们不需要进行多余的跳跃

2. 在上次选择节点覆盖范围最远的那个点,必须进行跳跃,选择 [上次选择节点, 上次选择节点覆盖范围最远的那个点] 之间覆盖最远的节点,理解看上图

根据两个思路实现

代码:

class Solution {
public:
    int jump(vector<int>& nums) {
        //总长度
        int len = nums.size();
        //上一个被选中结点最远的覆盖范围
        int lastJumpCoverage = 0;
        //最终跳跃的次数
        int resultMin = 0;
        //记录走过节点能覆盖的最远距离的状态
        int theFarthestDistance = 0;
        for(int i = 0; i < len; i++){
            //如果已经到最后一个了就直接break掉(有[0]情况)
            if(i == (len - 1)) break;
            if(lastJumpCoverage == i){
                theFarthestDistance = max((i + nums[i]), theFarthestDistance);
                //上次选的结点覆盖不到了,重新更新结点,当前节点最远距离和之前节点能到达的最远距离取最大
                lastJumpCoverage = theFarthestDistance;
                resultMin += 1;
            }else{
                //覆盖得到
                theFarthestDistance = max((i + nums[i]), theFarthestDistance);
            }
        }
        return resultMin;
    }
};

自己举了几个例子,算法都能满足,唯一不满足的可能就是类似 [ 0, 1 ], 第一个元素位置永远跳不到第二个元素的位置,这种情况不知道输出啥,但是看题目没说明就不管他了。

给 [0] 卡了一下

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_我走路带风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值