Jump Game

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

Determine if you are able to reach the last index..net

For example:
A = [2,3,1,1,4], return true.code

A = [3,2,1,0,4], return false.blog

解題思路:element

由於數組中都是非負整數,因此跨越不過去的必定是0。並且要注意A[i]是能跳的最遠距離,不是確定跳這麼遠。leetcode

因此當只要腳下不是0,均可以用最遠距離跳,確定到頭。一旦跳到0上,就從0這裏往回走一個,再跳,看看是否是超過以前0的位置。若是超過0,就證實能跨過這個0,繼續往前。若是還在這個0上,或者還沒到0,下標就再往回一個,而後跳,繼續判斷是否已經跳過0。重複,直到回到了數列盡頭。證實不管如何都不能跨過這個0了。返回false。it

public class Solution {
    public boolean canJump(int[] A) {
        int step = 0;
        int base = 0;
        while(true){
            if(step >= A.length - 1){
                return true;
            }
            if(A[step] == 0){
                base = step;
                while(step >= 0){
                    step--;
                    if(step < 0){
                        return false;
                    }
                    if(step + A[step] > base){
                        break;
                    }
                }
            }
            step += A[step];
        }
    }
}

不過上面的解法有缺陷,在最差狀況下,111101,要花2*n的時間,才能判斷結果爲false。io

下面介紹一個動態規劃的算法。其實一開始也想到用dp,dp[i]定義爲是否能到達i。dp[i] = dp[k] && (k + A[k] >= i),這裏0<=k<i。用的仍是上面的思路,還不如上面來的簡單。後來從網友那裏看到了一種更好的dp,http://blog.csdn.net/linhuanmars/article/details/21354751。

咱們能夠將dp[i]定義爲以i爲起點能夠到達的最遠距離,顯然就是i+A[i],這是當前局部的最優。那麼全局最優,也就是0-i的點可能到達的最遠距離顯然可能不是dp[i],由於可能i前面的點能跳的更遠,這是全局最優,叫maxReach。

有了這個思想,咱們一直往前遍歷A,用當前最遠距離dp[i]去更新全局最遠距離maxReach。i最遠只能到maxReach,由於這是當前最遠能到的地方,若是i超過maxReach了,證實根本到不了這裏,馬上返回false。

若是maxReach到A.length-1了,就說明能夠到頭,返回true。

public class Solution {
    public boolean canJump(int[] A) {
        int maxReach = 0;
        for(int i = 0; i < A.length; i++){
            if(maxReach < i){
                return false;
            }
            if(i + A[i] > maxReach){
                maxReach = i + A[i];
            }
            if(maxReach >= A.length - 1){
                return true;
            }
        }
        return false;
    }
}

這裏咱們再次看到,如何定義dp的子狀態是dp可否順利解決的關鍵。一樣是以dp的視角,不一樣的狀態定義獲得的解法多是徹底不一樣的複雜程度。

// 2018/09/17

class Solution {
    public boolean canJump(int[] nums) {
        int maxHere = 0, maxSoFar = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i > maxSoFar) {
                return false;
            }
            maxHere = Math.max(maxHere, i + nums[i]);
            maxSoFar = Math.max(maxSoFar, maxHere);
        }
        return true;
    }
}
相關文章
相關標籤/搜索