Skip to content

Latest commit

 

History

History
56 lines (50 loc) · 2.36 KB

55. Jump Game.md

File metadata and controls

56 lines (50 loc) · 2.36 KB

思路

给定一个非负数组成的数组,每个元素代表从当前位置能向前跳的最大步数,初始位置为第一个元素,问能否到达最后一个元素。

思路一、动态规划

开辟一个和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++

思路一

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;
    }
};

思路二

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;
    }
};