55 Jump Game i && 45 Jump Game ii

Jump Game

Problem statement:

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.

Analysis:

There are two solutions for this problem, one is greedy, another is dynamic programming. The main difference is the direction.

Solution one: 

Greedy is the best solution for this problem, it is always forwarding(AC) O(n).

  • Loop the whole array
  • Keep a right most position where I can get, update it at each index. 
  • if right most position is always greater than current index or it is already exceed the last position of array, return true since we can get the last position
  • Once current index is greater than right most position, return false, since there is already no way to get there.

The code is as following:

 1 class Solution {
 2 public:
 3     bool canJump(vector<int>& nums) {
 4         if(nums.empty()){
 5             return false;
 6         }
 7         
 8         // keep a indicator for current right most position we can reach
 9         int right_most = 0;
10         
11         // loop to enumrate all elements
12         for(int ix = 0; ix < nums.size(); ix++){ 
13             // if current element already exceed the right most position
14             // return false
15             if(right_most < ix){
16                 return false;
17             } else {
18                 // we already could reache the last element
19                 if(ix + nums[ix] >= nums.size() - 1){
20                     return true;
21                 } else {
22                     // otherwise, update the right most position
23                     right_most = max(ix + nums[ix], right_most);
24                 }
25             }
26         }
27         return false;
28     }
29 };

Solution two(NOT AC):

Dynamic programming O(n*n)

For dynamic programming, we looks back, for each element, we enumerate all the element whose index is lower than it, and check if it is reachable.

 1 class Solution {
 2 public:
 3     // dynamic programming solution
 4     bool canJump(vector<int>& nums) {
 5         if (nums.empty()) {
 6             return false;
 7         }
 8         int size = nums.size();
 9         vector<bool> true_table(size, false);
10         true_table[0] = true;
11         for(int i = 1; i < nums.size(); i++){
12             for(int j = 0; j < i; j++){
13                 if(true_table[j] && nums[j] + j >= i){
14                     true_table[i] = true;
15                     break;
16                 }
17             }
18         }
19         return true_table[size - 1];
20     }
21 };

--------------------------------- divide line --------------------------------------------

Jump Game ii

Problem Statement:

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

Note: You can assume that you can always reach the last index.

Analysis:

The main difference between jump game i && ii is that we should keep a minimum jump array for each element and update it for each element.

Solution one: Greedy

This is the accepted solution.

Solution two: Dynamic programming(NOT AC)

 1 class Solution {
 2 public:
 3     int jump(vector<int>& nums) {
 4         if(nums.empty()){
 5             return 0;
 6         }
 7         int size = nums.size();
 8         vector<bool> can_jump(size, false);
 9         vector<int> min_jump(size, INT_MAX);
10         // initialize start status
11         can_jump[0] = true;
12         min_jump[0] = 0;
13         // dynamic programming
14         for(int i = 1; i < nums.size(); i++){
15             for(int j = 0; j < i; j++){
16                 if(can_jump[j] && nums[j] + j >= i){
17                     can_jump[i] = true;
18                     min_jump[i] = min(min_jump[i], min_jump[j] + 1);
19                 }
20             }
21         }
22         // return end status
23         return min_jump[size - 1];
24     }
25 };

Solution two: Greedy(AC)

we keep two variables, the first one is the most right position in current jump, the second one is the right most position in next jump.

Just one loop to get the final solution:

 1 class Solution {
 2 public:
 3     int jump(vector<int>& nums) {
 4         // initialize 
 5         if(nums.size() < 2){
 6             return 0;
 7         }
 8         // variables
 9         int cur_jump_right_most = nums[0];
10         int next_jump_right_most = 0;
11         int min_jump = 1;
12         if(cur_jump_right_most >= nums.size() - 1){
13             return min_jump;
14         }
15         // O(n)
16         for(int ix = 1; ix < nums.size(); ix++){
17             if(ix > cur_jump_right_most){
18                 // at boundary 
19                 // update the cur_jump_right_most position before next_jump_right_most
20                 cur_jump_right_most = next_jump_right_most;
21                 min_jump++;
22             }
23             next_jump_right_most = max(next_jump_right_most, nums[ix] + ix);
24             if(next_jump_right_most >= nums.size() - 1){
25                 return ++min_jump;
26             }
27         }
28         return min_jump;
29     }
30 };
原文地址:https://www.cnblogs.com/wdw828/p/6414804.html