https://leetcode.com/problems/jump-game/
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.
Example 1:
Input: [2,3,1,1,4] Output: true Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.Example 2:
Input: [3,2,1,0,4] Output: false Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.
最开始想到的直观方法就是直接dp,从后往前记录每一个位置是否能到达终点,对每一个位置再向后遍历看能不能到达一个已知能够到达终点的点
class Solution {
public:
bool canJump(vector<int>& nums) {
if(nums.size() <= 1) return true;
vector<bool> dp(nums.size(), false);
dp[nums.size()-1] = true;
for(int i = nums.size()-2; i >= 0; --i){
for(int j = 1; j <= nums[i]; ++j){
if(dp[i+j] == true){
dp[i] = true;
break;
}
}
}
return dp[0];
}
};
但是效率很低,要用到三千多ms,原因是因为这个方法是用来找“正确路径”的,对任意一个点如果在他的覆盖范围内没有一直可行点的话,会遍历它的所有可能后继,所以对于无解的情况效率很低。
从上述算法的薄弱项出发,我们注意低效的遍历操作来源于题目中的“跳跃”并非是精准的,而是对一个范围的覆盖,同时我们也不关心正确的路径本身,我们希望有方法能够快速的确定“不可能”的情况。
综合考虑上述几点,我们可以注意到唯一的无解情况就是“跳不下去了”,因为只要能跳,在前进就必然能够到达终点,然后不知道为什么我就想到了这个方法。
class Solution {
public:
bool canJump(vector<int>& nums) {
static int fast_io = []() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();
int bound = 0;
for(int i = 0; i < nums.size(); ++i){
if(bound < i) return false;
bound = max(bound, i+nums[i]);
}
return true;
}
};