45. Jump Game II
题目:
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2
. (Jump 1
step from index 0 to 1, then 3
steps to the last index.)
Array Greedy
链接: http://leetcode.com/problems/jump-game-ii/
题解:
在Jump Game基础上还要计算最小jump数,所以除了maxCover外还需要维护一个lastCover。在当前i值超过lastCover所处index时,我们要把steps数加1。在循环结束后再判断是否满足能到达最后一个index,假如可以,返回steps,不可以则返回0。
Time Complexity - O(n), Space Complexity - O(1)。
public class Solution { public int jump(int[] nums) { if(nums == null || nums.length == 0) return 0; int maxCover = 0, lastCover = 0, steps = 0; for(int i = 0; i < nums.length && i <= maxCover; i++){ if(i > lastCover){ steps++; lastCover = maxCover; } if(i + nums[i] > maxCover) maxCover = i + nums[i]; } if(maxCover >= nums.length - 1) return steps; return 0; } }
二刷:
主要是使用了一种Greedy的思想来求最小步数。
- 首先我们设置不满足题意的corner case返回Integer.MAX_VALUE
- 接下来设置一个maxCover = 0, lastCover = 0, steps = 0。 maxCover代表我们当前能够到达的最大距离,lastCover等于之前的maxCover,用来记录我们在Greedy情况下每一跳的最远范围。
- 从0开始遍历数组,要注意条件是 i <= maxCover && i < nums.length
- 假如i > lastCover,这时候说明我们已经超过了之前记录的maxCover的范围,这个时候我们必须要进行一次跳跃,所以steps++,并且我们更新lastCover = maxCover,即上一条之后,我们这一次最远可以跳到哪里
- 假如i + nums[i] > maxCover, 这个时候我们更新maxCover = i + nums[i],可以继续进行接下来的计算
- 当循环结束时,我们检测maxCover是否 >= nums.length - 1
- 假如成立,则说明我们可以到达右边界,这时候返回steps
- 否则我们返回Integer.MIN_VALUE
看了一下discuss,这道题也可以用BFS来做。就是假设现在在0, 我们可以reach到 nums[0], 那我们接下来处理的就是在nums[0]范围内的数字,比如 1 和 2, 然后根据1 和 2的范围再继续找到下一层BFS,最后当范围包括到最后一个节点的时候我们返回这个层数。其实等同于一个非加权图中两点间最短路径问题。但没仔细看代码,复杂度怎么计算还不知道。
Java:
Time Complexity - O(n), Space Complexity - O(1)
public class Solution { public int jump(int[] nums) { if (nums == null || nums.length == 0) { return Integer.MAX_VALUE; } int maxCover = 0, lastCover = 0, steps = 0; for (int i = 0; i <= maxCover && i < nums.length; i++) { if (i > lastCover) { lastCover = maxCover; steps++; } if (i + nums[i] > maxCover) { maxCover = i + nums[i]; } } return maxCover >= nums.length - 1 ? steps : Integer.MAX_VALUE; } }
三刷:
方法跟上面一样。另外设置一个lastCover变量,每次当i > lastCover的时候,我们更新steps,并且设置lastCover = maxCover
Java:
public class Solution { public int jump(int[] nums) { if (nums == null || nums.length == 0) return 0; int maxCover = 0, lastCover = 0, steps = 0; for (int i = 0; i < nums.length && i <= maxCover; i++) { if (i > lastCover) { steps++; lastCover = maxCover; } maxCover = Math.max(maxCover, i + nums[i]); } return (maxCover >= nums.length - 1) ? steps : Integer.MAX_VALUE; } }
update:
当maxCover >= nums.length - 1时,我们可以跳过后面的计算。
public class Solution { public int jump(int[] nums) { if (nums == null || nums.length == 0) return 0; int maxCover = 0, lastCover = 0, steps = 0; for (int i = 0; i < nums.length && i <= maxCover; i++) { if (i > lastCover) { steps++; lastCover = maxCover; } maxCover = Math.max(maxCover, i + nums[i]); if (maxCover >= nums.length - 1) { if (lastCover >= nums.length - 1) return steps; else return steps + 1; } } return Integer.MAX_VALUE; } }
Reference:
https://leetcode.com/discuss/10588/o-n-bfs-solution
https://leetcode.com/discuss/13293/sharing-my-ac-java-solution
https://leetcode.com/discuss/30647/single-loop-simple-java-solution
https://leetcode.com/discuss/45992/10-lines-c-16ms-python-bfs-solutions-with-explanations
https://leetcode.com/discuss/67047/concise-o-n-one-loop-java-solution-based-on-greedy