55. 跳躍遊戲

給定一個非負整數數組,你最初位於數組的第一個位置。數組

數組中的每一個元素表明你在該位置能夠跳躍的最大長度。spa

判斷你是否可以到達最後一個位置。code

示例 1:blog

輸入: [2,3,1,1,4]
輸出: true
解釋: 從位置 0 到 1 跳 1 步, 而後跳 3 步到達最後一個位置。

示例 2:索引

輸入: [3,2,1,0,4]
輸出: false
解釋: 不管怎樣,你總會到達索引爲 3 的位置。但該位置的最大跳躍長度是 0 , 因此你永遠不可能到達最後一個位置。

 

思路1:最死板的動態規劃。從後往前記錄從位置i開始可否到達最後一個位置。每次判斷要基於以前的記錄結果遍歷1~nums[i]。io

其實這裏說的最大長度,就隱隱透露了這道題確定有更好更玄的解法....class

思路2:仍是從後往前,若是從位置i能到達最後一個位置,就記錄n=1,不然n+1。這裏n=1能夠理解爲中間沒有元素爲0,必定能夠到達;若是中間有1個0,就至少前面某個位置的數足夠大來跳過這個0,即至少須要值爲n來跳過0。遍歷

因此整個的邏輯就是,令n=1,若是nums[i]>=n,令n=1,不然n+1。遍歷結束後看n是否爲1,若是不爲1,而已是位置0,中間的0無法跳過,就到不了了。di

思路3:從前日後。記錄從位置i最遠能到達的地方d。位置i+1最遠能到達的地方=max(d, i+1 + nums[i+1]),進行這一步的前提是從i能到i+1.動態規劃

總的來講從後往前比較容易想,可是不容易作好,思路2仍是很差想明白。但從前日後的思路一旦想到了,就很簡單了。

class Solution {
public:
    bool canJump3(vector<int>& nums) {
        if(nums.empty()) return false;
        int n = nums.size();
        vector<int> vis(n,0);
        
        vis[n-1] = 1;
        for(int i = n - 2;i>=0;--i){
            if(nums[i] == 0) continue;
            
            int j1 = i + 1;
            int j2 = i + nums[i];
            if(j2 >= n){
                vis[i] = 1;continue;
            }
            while(j1<=j2 && !vis[j1]){
                ++j1;
            }
            if(j1<=j2 && vis[j1]) vis[i] = 1;
        }
        
        return vis[0];
    }
    bool canJump2(vector<int>& nums) {
        if(nums.empty()) return false;
        
        int n = 1;
        for(int i = nums.size() - 2;i>=0;--i){
            if(nums[i] >= n) n = 1;
            else ++n;
        }
        
        return n==1;
    }
    
    bool canJump(vector<int>& nums) {
        if(nums.empty()) return false;
        
        int d = 0;
        for(int i = 0;i<nums.size() - 1 && d>=i;++i){
            d = max(d,i + nums[i]);
        }
        return d >= nums.size() - 1;
    }
};
相關文章
相關標籤/搜索