问题描述
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。
解决思路
题目要求从第一个跳到最后一个,如果能知道中间的是否可以跳到最后一个,那么第一个是否能跳到也就能相应判断
* 采用动态规划的方式从后往前跳,判断当前位置是否可以跳到最后一个元素,一直判断到第一个元素。
* 时间复杂度O(n^2),因为每个元素都要与其右边的元素相参照,右边元素最多达到n个。
* 空间复杂度O(n),只需要开辟一个DP数组。
代码呈现
1 public static boolean canJump(int[] nums) {
2 int length = nums.length;
3 if (length==0) { return true; }
4 boolean[] DP = new boolean[length];
5 Arrays.fill(DP, false);
6 DP[length-1] = true;
7
8 for ( int i=length-2; i>=0; i--) {
9 if (nums[i] >= length-i-1) {
10 DP[i] = true;
11 continue;
12 } else {
13 for (int j=nums[i]; j>=0; j--) {
14 if (DP[i+j]) {
15 DP[i] = true;
16 break;
17 }
18 }
19 }
20 }
21 for(boolean a : DP) {
22 System.out.print(a + " ");
23 }
24 System.out.println();
25 return DP[0];
代码改进
如果我们用一个单独的变量来记录最左边的 GOOD 位置(该位置可以到达最后一个元素),那么就不用在遍历当前元素的时候搜索整个右边数组,进而可以省略整个 DP 数组,且每个元素最多遍历一次。
时间复杂度O(n),空间复杂度O(1)。1 public boolean canJump2(int[] nums) { 2 int lastPos = nums.length - 1; 3 for (int i = nums.length - 1; i >= 0; i--) { 4 if (i + nums[i] >= lastPos) { 5 lastPos = i; 6 } 7 } 8 return lastPos == 0; 9 }