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.

Determine if you are able to reach the last index.

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

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

解题思路:

因为数组中都是非负整数,所以跨越不过去的一定是0。而且要注意A[i]是能跳的最远距离,不是肯定跳这么远。

所以当只要脚下不是0,都可以用最远距离跳,肯定到头。一旦跳到0上,就从0这里往回走一个,再跳,看看是不是超过之前0的位置。如果超过0,就证明能跨过这个0,继续往前。如果还在这个0上,或者还没到0,下标就再往回一个,然后跳,继续判断是否已经跳过0。重复,直到回到了数列尽头。证明无论如何都不能跨过这个0了。返回false。

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。

下面介绍一个动态规划的算法。其实一开始也想到用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;
    }
}

 

转载于:https://www.cnblogs.com/NickyYe/p/4360802.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值