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

时间:2022-11-09 18:55:55

跳跃游戏 II
给出一个非负整数数组,你最初定位在数组的第一个位置。
数组中的每个元素代表你在那个位置可以跳跃的最大长度。   
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
样例
给出数组A = [2,3,1,1,4],最少到达数组最后一个位置的跳跃次数是2(从数组下标0跳一步到数组下标1,然后跳3步到数组的最后一个位置,一共跳跃2次)
标签
贪心 数组

(1)Java

public class JumpGame_II {
    // Greedy 在DP超时情况下,只能试着用greedy了!AC
    // Version 2 Greedy1
    public static int jump2(int[] A) {

        int jmp = 0;
        int dest = A.length - 1;        // destination index

        while(dest != 0){       // 不断向前移动dest
            for(int i = 0; i < dest; i++){
                if(i + A[i] >= dest){       // 说明从i位置能1步到达dest的位置
                    dest = i;       // 更新dest位置,下一步就是计算要几步能调到当前i的位置
                    jmp++;
                    break;      // 没必要再继续找,因为越早找到的i肯定越靠前,说明这一跳的距离越远
                }
            }
        }
        return jmp;
    }

// Version 2 Greedy2
public class Solution {
    public int jump(int[] A) {
        if (A == null || A.length == 0) {
            return -1;
        }
        int start = 0, end = 0, jumps = 0;
        while(end < A.length - 1){
            int farthest = end;
            for(int i = start; i <= end; i++){ // 本层循环不可漏写!! 
                if(i + A[i] > farthest){
                    farthest = i + A[i];
                }
            }
            start = end + 1;
            end = farthest;
            jumps++;// 跳出说明end >= A.length - 1,此后无需再jump++
        }
        return jumps;
    }
}


// 动归
// version 1: Dynamic Programming
// 这个方法,复杂度是 O(n^2),会超时,但是依然需要掌握。
class JumpGame01 {
    public int jump(int[] A) {
        // state
        int[] steps = new int[A.length];

        // initialize
        steps[0] = 0;
        for (int i = 1; i < A.length; i++) {
            steps[i] = Integer.MAX_VALUE;
        }

        // function
        for (int i = 1; i < A.length; i++) {
            for (int j = 0; j < i; j++) {
                if (steps[j] != Integer.MAX_VALUE && j + A[j] >= i) {
                    steps[i] = Math.min(steps[i], steps[j] + 1);
                }
            }
        }

        // answer
        return steps[A.length - 1];
    }
}

(2)C++

① Version 1
class JumpGameII{
public:
    int jump(vector<int> &nums){
        if(nums.size() <= 1){// 若数组长度<= 1 则不用跳跃,返回0
            return 0;
        }
        int cur_max_i= nums[0];
        int pre_max_i = nums[0];
        int jump_min = 1;// 最少跳跃次数
        for(int i = 0; i < nums.size(); i++){
            if(i > cur_max_i){//❤️ 贪心思想: 若无法再向前移动了,才进行跳跃(如: 走到i+1了,而cur_max_i还只更新到i)
                jump_min++;
                cur_max_i = pre_max_i;// 即更新当前可到达的最远位置
            }
            if(pre_max_i < i + nums[i]){ // i + nums[i] 即为index[i],即最远跳至的下标
                pre_max_i = i + nums[i];
            }
        }//❤️ 注意以上两if不可颠倒!
        return jump_min;
    }
};

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);
    JumpGameII jg2;
    cout << jg2.jump(nums) << endl;
    return 0;
}

其他:
Greedy
Two Pointers