Leetcode | Jump Game I && II

Jump Game I

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], return true.

A = [3,2,1,0,4], return false.

Method I

动态规划。reachable[i]存的是能不能从i跳到n-1。

如果存在1<=j<=A[i],使得reachable[i+j]=true,那么reachable[i]=true;否则reachable[i]=false;

但是这样穷搜的话会TLE。所以需要继续避免一些计算。

如果A[i]<=A[i+1]+1时,只要A[i]不为0,那么i必定能够跳到i+1,i能够跳到的位置,i+1都能跳到,所以reachable[i]=reachable[i+1];

如果A[i]>A[i+1]+1时,因为从i往后A[i + 1]+1都已经在计算reachable[i+1]的时候计算过了。如果此时reachable[i+1]=false,我们就从i往后A[i+1]+2开始跳。

 1 class Solution {

 2 public:

 3     bool canJump(int A[], int n) {

 4         if (n == 0) return true;

 5         

 6         vector<bool> reachable(n, false);

 7         reachable[n - 1] = true;

 8         

 9         for (int i = n - 2; i >= 0; --i) {

10             if (A[i] == 0) continue;

11             if (n - 1 - i <= A[i]) {

12                 reachable[i] = true;

13             } else {

14                 reachable[i] = reachable[i + 1];

15                 if (reachable[i]) continue;

16                 for (int j = A[i + 1] + 2; j <= A[i]; ++j) {

17                     if (reachable[i + j]) {

18                         reachable[i] = true;

19                         break;

20                     }

21                 }

22             }

23         }

24         

25         return reachable[0];

26     }

27 };

以前说的好复杂。。。

 1 class Solution {

 2 public:

 3     bool canJump(int A[], int n) {

 4         if (n <= 1) return true;

 5         vector<bool> dp(n, false);

 6         dp[0] = true;

 7         for (int i = 1; i < n; ++i) {

 8             if (!dp[i - 1]) dp[i] = false;

 9             else {

10                 for (int j = i - 1; j >= 0; --j) {

11                     if (A[j] && A[j] >= i - j) {

12                         dp[i] = true;

13                         break;

14                     }

15                 }

16             }

17         }

18         return dp[n - 1];

19     }

20 };

Method II

参考了水中的鱼的算法, 更简单。算出一个最大的覆盖区间maxcover,如果i在这区间里,用它能跳到的最远位置来更新maxcover。

当然你也可以把它理解为动态规划的一种。Code Granker 总结的”局部最优和全局最优解法“的一种。

 1 class Solution {

 2 public:

 3     bool canJump(int A[], int n) {

 4         int maxcover = 0;

 5         

 6         for (int i = 0; i < n && i <= maxcover; ++i) {

 7             if (A[i] + i > maxcover) maxcover = A[i] + i;

 8             if (maxcover >= n - 1) return true;

 9         }

10         return false;

11     }

12 };

 

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.)

Method I

同上,但是要分的情况更多了。76ms accept.

min[i]就是从i跳到n-1的最小步数;

1. A[i] == 0,不可达;

2. n-1-i <= A[i],一步可达;

3. A[i] == 1,min[i] = min[i +1]+1; 先跳到i+1,再从i+1往向跳;

4. A[i] == A[i+1] +1,那么从i+1可以跳到的位置,i也可以一步跳到,所以min[i] = min[i+1];

5. 剩下的情况,就要尝试i能跳到的范围,求最小步数了;

 1 class Solution {

 2 public:

 3     int jump(int A[], int n) {

 4         if (n == 0) return 0;

 5         

 6         vector<int> min(n, n + 1);

 7         min[n - 1] = 0;

 8         

 9         for (int i = n - 2; i >= 0; --i) {

10             if (A[i] == 0) continue;

11             if (n - 1 - i <= A[i]) {

12                 min[i] = 1;

13             } else if (A[i] == 1) {

14                 min[i] = min[i + 1] + 1;

15             } else if (A[i] == A[i + 1] + 1) {

16                 min[i] = min[i + 1];

17             }else {

18                 int m = min[i];

19                 for (int j = 1; j <= A[i]; ++j) {

20                     if (min[i + j] + 1 < m) {

21                         m = min[i + j] + 1;

22                     }

23                 }

24                 min[i] = m;

25             }

26         }

27         

28         return min[0];

29     }

30 };

如果之前走到从A[min]到A[i-1]能走到最小,如果此时A[min]也能走到A[i],那么可以直接从min跳到i就是最小步数了。不然还得穷搜一下。

 1 class Solution {

 2 public:

 3     int jump(int A[], int n) {

 4         if (n <= 1) return 0;

 5         vector<int> dp(n, n);

 6         dp[0] = 0;

 7         int minIndex = 0;

 8         for (int i = 1; i < n; ++i) {

 9             if (dp[i - 1] == n) {

10                 dp[i] = n;

11             } else if (i > 1 && A[minIndex] >= i - minIndex) {

12                 dp[i] = dp[i - 1];

13             } else {

14                 for (int j = i - 1; j >= 0; --j) {

15                     if (A[j] >= i - j && dp[j] + 1 < dp[i]) {

16                         dp[i] = dp[j] + 1;

17                         minIndex = j;

18                     }

19                 }

20             }

21         }

22         

23         return dp[n - 1];

24     }

25 };

 

Method II

 如水中的鱼的解法。维护一个最大覆盖区间,计算覆盖区间的个数就是最小步数。

 1 class Solution {

 2 public:

 3     int jump(int A[], int n) {

 4         if (n <= 1) return 0;

 5         int s = 0, e = 0, count = 0;

 6         

 7         while (s <= e && e < n) {

 8             count++;

 9             int max = 0;

10             for (int i = s; i <= e; ++i) {

11                 if (A[i] + i > max) max = A[i] + i;

12                 if (max >= n - 1) return count;

13             }

14             s = e + 1;

15             e = max;

16         }

17         return 0;

18     }

19 };

 

你可能感兴趣的:(LeetCode)