【leetcode每日刷题】55. Jump Game

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/m0_38103546/article/details/100751386

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.

Example 1:

Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.

Example 2:

Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
             jump length is 0, which makes it impossible to reach the last index.

1、回溯/递归

采用递归的方法,从开始看是否能到达最后

2,3,1,1,4

0->2->3->4

class Solution {
    public static boolean canJump(int[] nums) {
       return canJumpFromPosition(0, nums);
    }
    public static boolean canJumpFromPosition(int pos, int[] nums){
        if(pos == nums.length - 1) return true;
        int furthest = Math.min(pos+nums[pos], nums.length-1);
        for(int i = furthest; i>pos; i--){
            if(canJumpFromPosition(i, nums)) return true;
        }
        return false;
    }
}

2、自顶向下的动态规划

自顶向下动态规划可以看作是优化的回溯。它依赖于这样的观察: 一旦我们确定某个指标是好/坏,这个结果就永远不会改变。这意味着我们可以存储结果,而不需要每次都重新计算它。

因此,对于数组中的每个位置,我们都会记住索引是好是坏。让我们调用这个数组memo,让它的值是:GOOD, BAD, UNKNOWN。

输入数组nums =[2,4,2,1,0,2,0]的记忆表示例如下图所示。G代表好的位置B代表坏的位置。我们可以看到,我们不能从索引2、3或4开始,最后到达索引6,但是我们可以从索引0、1、5和6开始。

enum Index{
    Good, Bad, Unknown
}
class Solution {
    Index[] memo;
    public boolean canJump(int[] nums) {
        memo = new Index[nums.length];
        for(int i=0; i<nums.length; i++){
            memo[i] = Index.Unknown;
        }
        memo[nums.length-1] = Index.Good;
       return canJumpFromPosition(0, nums);
    }
    public boolean canJumpFromPosition(int pos, int[] nums){
        if(memo[pos] != Index.Unknown) return memo[pos] == Index.Good? true:false;
        int furthest = Math.min(pos+nums[pos], nums.length-1);
        for(int i = pos+1; i <= furthest; i++){
            if(canJumpFromPosition(i, nums)) {
                memo[i] = Index.Good;
                return true;
            }
        }
        memo[pos] = Index.Bad;
        return false;
    }
}

3、自底向上的动态规划,将自顶向下的递归算法进行消除递归改为循环操作。

enum Index{
    Good, Bad, Unknown
}
class Solution {
    Index[] memo;
    public boolean canJump(int[] nums) {
        memo = new Index[nums.length];
        for(int i=0; i<nums.length; i++){
            memo[i] = Index.Unknown;
        }
        memo[nums.length-1] = Index.Good;
        for(int i=nums.length-2; i>=0; i--){
            int furthest = Math.min(i+nums[i], nums.length-1);
            for(int j=i+1; j<=furthest; j++){
                if(memo[j] == Index.Good){
                    memo[i] = Index.Good;
                    break;
                }
            }
        }
        return memo[0]==Index.Good;
    }
}

4、贪婪算法


class Solution {
    public boolean canJump(int[] nums) {
        int lastpos = nums.length-1;
        for(int i=nums.length-1; i>=0; i--){
            if(i + nums[i] >= lastpos){
                lastpos = i;
            }
        }
        return lastpos == 0;
    }
}

从最后一点向前遍历,看每个元素是否能到达,如果能够到达,将该点标记为lastpos

猜你喜欢

转载自blog.csdn.net/m0_38103546/article/details/100751386