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;
    }
}
相关文章
相关标签/搜索