LeetCode 热题 HOT 100 第25天:“跳跃游戏”

继续刷LeetCode 热题 HOT 100 的题目,并且在博客更新我的solutions。在csdn博客中我会尽量用文字解释清楚,相关Java代码大家可以前往我的个人博客jinhuaiyu.com中查看。
题目:跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
提示:
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105

solution:贪心算法
在讲具体步骤之前,我们先分析一下题目。如果只是简单地看,只会有三种情况:1、该数组中没有0,则一定能到达尾部;2、该数组中有若干个0,但每个0都能被跨过,比如i位置是第一个0,那么0到i-1位置中一定至少有一个数比这个位置到第一个0的距离大(跨过);3、该数组中有若干个0,但其中至少有一个0不能被跨过,比如4321012这组数字,0就无法被跨过。
这样看来,我们要分析每一个0能不能被跨过(即每一个0之前的数有没有大于两者距离的)。但是我们做题不是为了做一道题,而是为了做一类题,通过看评论区,我发现大家也有这种看法,就是这道题不是为了让大家去针对0进行分析,而是为了得出一种思想,对于这道题来说就是对每个数都要进行分析(但显然,这道题里如果没有0那肯定能到达尾部)。
如果用动态规划分析每个位置能不能被跨过,那时间复杂度至少是O(n²),我们需要思考的是怎么通过一轮遍历来分析。
我们也不需要维护每一个位置能跳到最远的距离,假设目前已经能到位置i,我们只需要维护前面所有位置能跳到最远处中最远的位置,farthest变量记录它,初始化为0。此时我们的移动并不是通过考虑能跳到什么位置,而是直接遍历每一个位置。从左往右遍历,如果当前位置在farthest内(说明当前位置是能跳到的),就可以继续遍历(位置+1),当然,需要通过对比原farthest和当前位置能跳到最远的位置来更新farthest。这种更新farthest可以看作是动态规划的一种变形,因为每次移动,都要看这个位置是否能从以前的位置跳过来(不超过farthest)。如果某次更新的farthest已经超过数组最后位置,说明能到达尾部,不用再往前移动一位来分析了。如果当前遍历位置超过了之前所有位置能达到的最远位置(不在farthest内了),说明这一步位置都根本到不了,更别说后面的位置了,此时跳出循环返回false。
其实这个循环遍历就是探讨当前位置能否达到,并更新前面(包括这个位置)所有能达到的位置中能跳到的最远处位置,不论你是跳几步,最远都只能到那,如果超过数组长度,说明能到尾部;如果中间某一个位置无法达到,说明到不了尾部。
这是一种从前往后遍历分析的方法,我们也可以从后往前分析,甚至还有其他的变形,但是理论都是这一套,去分析当前位置能否达到。

Finally,带有详细注释的代码放在我的个人博客http://jinhuaiyu.com/leetcode-jump-game/

你可能感兴趣的:(LeetCode,leetcode,算法,贪心算法)