LeetCode/solutions/55. Jump Game.md
2019-01-17 23:27:55 +08:00

57 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [55. Jump Game](https://leetcode.com/problems/jump-game/)
# 思路
给定一个非负数组成的数组,每个元素代表从当前位置能向前跳的最大步数,初始位置为第一个元素,问能否到达最后一个元素。
## 思路一、动态规划
开辟一个和nums同样大小的数组can_reach其代表的意思是: 若`can_reach[i]==1`说明从位置i可以到达最后一个位置若`can_reach[i]==0`则说明不能到达。
所以最后的返回结果就是`can_reach[0]`。
那我们该怎样求`can_reach[i]`呢? 我们知道从位置i能到达的最远位置是`i+nums[i]`,所以我们只需要看在这个区间内是否有满足能到达的就可以了,即若存在
j属于[i+1, i+nums[i]],使得`can_reach[j]`为1那么`can_reach[i]=1`,否则`can_reach[i]=0`。
所以我们应该从后往前算can_reach。
若nums中所有元素都为0则是最坏情况此时得出时间复杂度为O(n^2)空间复杂度为O(n)。
## 思路二、贪心
思路一的时间复杂度比较高,仔细分析题目可得出更快的解法。
其实我们用贪心就可以解决此问题从后往前遍历数组nums用d记录直到此时能到达的最远的位置。假设此时遍历到了位置i如果出现了`d < i`说明根本到达不了位置i更别说到达
最后一个位置了所以直接返回false即可`d >= n - 1`说明此时就可以到达最后一个位置了所以直接返回true即可否则更新d: `d = max(d, i + nums[i])`
这种方法最多只遍历了一遍数组所以时间复杂度为O(n)空间复杂度显然为O(1)。
# C++
## 思路一
``` C++
class Solution {
public:
bool canJump(vector<int>& nums){
int n = nums.size();
int can_reach[n] = {0};
can_reach[n - 1] = 1;
for(int i = n - 2; i >= 0; i--)
for(int j = 1; j <= nums[i]; j++)
if(can_reach[i + j]){
can_reach[i] = 1;
break;
}
return can_reach[0] == 1;
}
};
```
## 思路二
``` C++
class Solution {
public:
bool canJump(vector<int>& nums){
int n = nums.size();
int d = 0;
for(int i = 0; i < n; i++){
if(d < i) return false;
if(d >= n - 1) return true;
d = max(d, i + nums[i]);
}
return false;
}
};
```