LeetCode 45. Jump Game II 跳跃游戏II,求最少跳跃次数 (贪心)

https://leetcode.com/problems/jump-game-ii/description/

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

说明:
假设你总是可以到达数组的最后一个位置。

题解:
跳跃问题1 中求能否到达最后位置,用一个 reach 变量 记录能够到达的最远的下标,每走一步比较更新该值,到达最终位置前,如果当前下标大于reach,说明失败。如果能到达最后,说明成功。

而这道题,需要求的是最少的步数。因此需要添加 count 变量记录最少步数。什么时候 count++ 是问题的关键?答案是当前的位置 i 超过了上一跳所能到达的最远位置。所以需要引入变量 last 记录上一跳可达最远坐标。此题代码在跳跃问题1 代码基础上修改。

class Solution {
    public int jump(int[] nums) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int reach = 0;//当前所能到达的最远坐标
        int last = 0;//上一跳可达最远坐标
        int count = 0;//跳跃次数
        for (int i = 0; i < nums.length; i++) {
            if (i > reach) {
                return -1;
            }
            if (i > last) {
                count++;
                last = reach;
            }
            if (i + nums[i] > reach) {
                reach = i + nums[i];
            }
        }
        return count;
    }
}

动态规划解法:
复杂度是 O ( n 2 ) ,会超时,但是依然需要掌握。

定义状态:dp[i] 表示到达 i 位置的最小跳数
起始装填:dp[0]=0 到达下标0的最小跳数是0
终止状态:dp[nums.length-1] 即到达最后一个位置的最小跳数
决策:选择 i 之前的能跳到 i 的所有位置j 中, dp[j] 值最小的位置 j 作为上一步要跳到 i 的位置
费用表示:dp[i]=dp[j]+1 ,从 j 跳到 i ,步数加1
无后效性:收益1 是个常数,不随状态改变

class Solution {
    public int jump(int[] nums) {
        int[] dp = new int[nums.length];//dp[i] 为到达 i 位置的最小跳数
        dp[0] = 0;//到达下标0的最小跳数是0
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Integer.MAX_VALUE;
            for (int j = 0; j < i; j++) {
                if (i - j <= nums[j]) {
                    dp[i] = Math.min(dp[i], dp[j] + 1);
                }
            }
        }
        return dp[nums.length - 1];
    }
}

猜你喜欢

转载自blog.csdn.net/zxm1306192988/article/details/80738332