【LeetCode】Jump Game 跳跃游戏 - 贪心 - Medium

给出一个非负整数数组,你最初定位在数组的第一个位置。   
数组中的每个元素代表你在那个位置可以跳跃的最大长度。    
判断你是否能到达数组的最后一个位置。
注意事项
这个问题有两个方法,一个是贪心和 动态规划。
贪心方法时间复杂度为O(N)。
动态规划方法的时间复杂度为为O(n^2)。
我们手动设置小型数据集,使大家可以通过测试的两种方式。这仅仅是为了让大家学会如何使用动态规划的方式解决此问题。如果您用动态规划的方式完成它,你可以尝试贪心法,以使其再次通过一次。

样例
A = [2,3,1,1,4],返回 true.
A = [3,2,1,0,4],返回 false.
标签
贪心 数组 动态规划
相关题目
中等 流浪剑客斯温 32 %
中等 跳跃游戏 II 35 %

(1)Java

package Greedy;

// version 2: Greedy
public class JumpGame {
    public boolean canJump(int[] A) {
    // think it as merging n intervals
    if (A == null || A.length == 0) {
        return false;
    }
    int farthest = A[0];
    for (int i = 1; i < A.length; i++) {
        if (i <= farthest && A[i] + i >= farthest) {
            farthest = A[i] + i;
        }
    }
    return farthest >= A.length - 1;
    }
}

// version 1: Dynamic Programming
// 这个方法,复杂度是 O(n^2) 可能会超时,但是依然需要掌握。
class JumpGame1 {
    public boolean canJump(int[] A) {
        boolean[] can = new boolean[A.length];
        can[0] = true;

        for (int i = 1; i < A.length; i++) {
            for (int j = 0; j < i; j++) {
                if (can[j] && j + A[j] >= i) {
                    can[i] = true;
                    break;
                }
            }
        }

        return can[A.length - 1];
    }
}
③维护一个right (表示右边能跳到的最远的点),从左往右扫描,根据当前可跳的步骤不断更新right ,当right到达终点,即可返回true. 若更新完right后,right未动,并且index = right,而且这时没到达终点,代表我们不可能到达终点了。(当前index的可跳值应该是0)。
class JumpGame2 {
    // solution 3: one pass.
    public boolean canJump(int[] A) {
        // 4:42
        if (A == null) {
            return false;
        }

        int len = A.length;

        int right = 0;
        for (int i = 0; i < A.length; i++) {
            right = Math.max(right, i + A[i]);
            if (right == len - 1) {
                return true;
            }

            if (i == right) {
                return false;
            }
        }

        return true;
    }
}

其他方法:www.cnblogs.com/yuzhangcmu/p/4039840.html

(2)C++

class JumpGame{
public:
    bool canJump(vector<int>& nums){
        vector<int> index;// 每个位置i处所能 最远跳至的index下标
        for(int i = 0; i < nums.size(); i++){
            index.push_back(i + nums[i]);// index保存最远可跳达的下标。若当前在i处 已知最远可以跳到下标为 index[i]处,则比较其与farthest大小。 直到farthest >= 最大下标,说明可以跳至终点。
        }
        int jump = 0;
        int farthest = index[0];

        while (jump < index.size() && jump <= farthest) {
            if(farthest < index[jump]){// jump是从0开始往后扫描。 index[jump]是当前最远能到达的下标(i + nums[i])
                farthest = index[jump];// 若当前可以跳的更远,则更新farthest
            }
            jump++;
        }

        if(jump == index.size()){
            return true;
        }
        return false;
    }
};

//int main()
//{
//    vector<int> nums;
//    nums.push_back(2);
//    nums.push_back(3);
//    nums.push_back(1);
//    nums.push_back(1);
//    nums.push_back(4);
//    JumpGame jg;
//    cout << jg.canJump(nums) << endl;
//    return 0;
//}


class JumpGameV2 {
public:
    bool canJump(vector<int> A) {
        int tmpMax = 0;
        int n = A.size();
        for (int i = 0; i < n; i++) {
            if (i > tmpMax) return false;
            if (tmpMax < i + A[i])
                tmpMax = i + A[i];
        }
        return true;
    }
};

猜你喜欢

转载自blog.csdn.net/ljyljyok/article/details/79693459