55(45)-跳跃游戏Ⅰ、Ⅱ-贪心算法

写在前面

贪心算法说简单也简单,因为找到局部的最优解就可以了,说难也确实不是很好想,因为这种思想在想的时候总会有种不那么确定的感觉,想证明的话又会变得很复杂,虽然不需要证明,但是总是不太敢写。

题目一

核心思路

这种类型的题如果当做模拟来做的话,还是比较好写的,不过起码需要O(n²)的复杂度,显然是不想接受的。
观察题目跳跃的规则,可以发现,如果 i 位置可达,那么从 i 到 i + nums[i] 中间的下标都是可达的,那么只要存储当前最远能到达的位置max,比较maxi + nums[i]的大小更新max,这样就能找到最远跳到的位置,不过如果当前遍历到的位置i已经是不可达的了,就显然不能到达最后一个位置,因此此时应该返回false,期间遍历的位置都是可达的,那么最终返回true即可。

图示

代码

class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        int max = 0;
        for(int i = 0; i < n && max < n; i++){
            if(i > max){
                return false;
            }else{
                max = Math.max(max, i + nums[i]);
            }
        }
        return true;
    }
}

题目二

核心思路一 - 动态规划

跳跃游戏Ⅱ与Ⅰ规则虽然没变,但是需要求解的结果变了很多,不再是只要能到达数组最后即可,而是默认能到,需要求最小的跳跃步数。实话说,我做完第一题做的这道,想了一会儿还是没什么贪心的思路,而是想要使用一个数组然后动态规划来解决,虽然动态规划实际上与贪心算法很像,但是我还是没有那种思路,还需要一点点的积累。
定义一个数组counts[i]来记录开头位置最少需要几步到达i位置,那么对于counts[i],从下标i + 1i + nums[i]都等于count[i] + 1,不过这中间访问的位置可能是下标i之前的下标就访问过的,所以可以取一个最小值,不过其实没有必要,因为前边更新过的数一定比当前i更新的数值小,所以可以备份一个max值,表示之前一条最远能跳到的位置,只有i + nums[i]大于max时,才需要更新counts,于是我们可以得到下边这样的代码。

图示

代码

class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int index = 0;//当前遍历的下标
        int max = 0;//前一跳的最远距离
        int[] counts = new int[n];//最短需要跳的步数
        while (index < n) {
            int temp = index + nums[index];
            if (temp > max) {
                for (int i = max + 1; i <= temp && i < n; i++) {
                    counts[i] = counts[index] + 1;
                }
                max = temp;
            }
            index++;
        }
        return counts[n - 1];
    }
}

虽然可以较高效的解决问题,但是需要额外使用O(n)的空间。

核心思路二 - 贪心

既然想要贪心,想要跳的步数少,那么每一步就要跳的尽量远,而最远的地方就是i+nums[i],所以直到遍历到前一步能跳的最远的位置时,才去考虑下一步,这样到终点时就会有两种情况,一是刚好前一步的结尾是终点,二是前一步已经越过终点了,这两种情况的结果会差一,可以分类讨论,不过可以更巧妙,也就是直接忽略最后的终点位置,因为题目保证了可以到达,我们只遍历到倒数第二个位置就已经可以保证到终点了,这样就省去了额外的判断。

代码

class Solution {
    public int jump(int[] nums) {
        int end = 0;//上一跳能跳到的最远位置
        int max = 0; //当前最远的位置
        int count = 0;//总跳数

        for(int i = 0; i < nums.length - 1; i++){
            max = Math.max(max, nums[i] + i); 
            if(i == end){
                end = max;
                count++;
            }
        }
        return count;
    }
}

总结

虽然之前也写过几道贪心题,但是这种思想还是很不好理解,还是需要好好的训练一下啊。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容