Skip to main content

【LeetCode 45】跳跃游戏 II

·134 words·1 min
WFUing
Author
WFUing
A graduate who loves coding.
Table of Contents

dp 解法
#

class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n+1];
        for(int i=2;i<=n;i++) {
            dp[i] = Integer.MAX_VALUE/2;
        }
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=nums[i-1];j++){
                if((i+j)>n) break;
                dp[i+j] = Math.min(dp[i]+1,dp[i+j]);
            }
        }
        return dp[n];
    }
}

正向查找可到达的最大位置
#

方法一虽然直观,但是时间复杂度比较高,有没有办法降低时间复杂度呢?

如果我们「贪心」地进行正向查找,每次找到可到达的最远位置,就可以在线性时间内得到最少的跳跃次数。

例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。

从下标 1 出发,最远可到达下标 4。下标 1 可到达的位置中,下标 4 的值是 4 ,从下标 4 出发可以达到更远的位置,因此第二步到达下标 4。

在具体的实现中,我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。

在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。

class Solution {
    public int jump(int[] nums) {
        int length = nums.length;
        int end = 0;
        int maxPosition = 0; 
        int steps = 0;
        for (int i = 0; i < length - 1; i++) {
            maxPosition = Math.max(maxPosition, i + nums[i]); 
            if (i == end) {
                end = maxPosition;
                steps++;
            }
        }
        return steps;
    }
}