先看一下这个问题:
LeetCode 55. Jump Game
Question
如果从某个索引位置能到达最后一个索引,那我们就称这个位置为 "good index", 否则,称为"bad index".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.
Determine if you are able to reach the last index.
For example:
A =[2,3,1,1,4]
, returntrue
.A =
[3,2,1,0,4]
, returnfalse
.
这是一个动态规划问题,通常解决动态规划问题的思路如下:
1.考虑递归回溯方法(recursive backtracking solution)
2.利用存储表来进行优化的递归方法(top-down 自上而下的动态规划)
3.不使用递归(bottom-up自底向上的动态规划)
4.final tricks to reduce thi time/ memory complexity
Approach #1 (Backtracking) [Stack Overflow]
这是一种低效方法,从first positon开始,跳到每一种可能到达的位置。重复这个过程,直到到达最后的位置。如果中途中断,则backtrack。在此基础上的优化是:在每次判断下一个位置是否能够到达时,先判断它的最远到达位置,如果能到的最远的那个位置是可以到达 的,就不用再判断前面的了。这样可以在实际情况中减少很多次判断的可能。如果远的地方的不行,在一点点往回减1,进行下一轮的判断。
时间复杂度O(2^n)
空间复杂度O(n)
Approach #2 (Dynamic Programming Top-down) [Stack Overflow]
nums = [2, 4, 2, 1, 0, 2, 0]
对应的存储数组为:
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
nums | 2 | 4 | 2 | 1 | 0 | 2 | 0 |
memo | G | G | B | B | B | G | G |
Approach #3 (Dynamic Programming Bottom-up) [Time limit exceeded]
enum Index {
GOOD, BAD, UNKNOWN
}
public class Solution {
public boolean canJump(int[] nums) {
Index[] memo = new Index[nums.length];
for (int i = 0; i < memo.length; i++) {
memo[i] = Index.UNKNOWN;
}
memo[memo.length - 1] = Index.GOOD;
for (int i = nums.length - 2; i >= 0; i--) {
int furthestJump = Math.min(i + nums[i], nums.length - 1);
for (int j = i + 1; j <= furthestJump; j++) {
if (memo[j] == Index.GOOD) {
memo[i] = Index.GOOD;
break;
}
}
}
return memo[0] == Index.GOOD;
}
}
时间复杂度O(n^2)
空间复杂度O(n)
Approach #4 (Greedy) [Accepted]
时间复杂度O(n)
空间复杂度O(1)
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
nums | 9 | 4 | 2 | 1 | 0 | 2 | 0 |
memo | U | G | B | B | B | G | G |
public class Solution {
public boolean canJump(int[] nums) {
int leftmostGoodIndex=nums.length-1;
for(int j=nums.length-2;j>=0;j--){
if(j+nums[j]>=leftmostGoodIndex){
leftmostGoodIndex=j;
}
}
return leftmostGoodIndex==0;
}
}