leetcode55. 跳跃游戏 45. 跳跃游戏 II


我写的第一份通过的代码,问题在于重复更新浪费不少时间,内层循环可能会重复更新许多已经确定不是最优解的位置。
class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n]; //dp[i]表示到达此处的最小跳跃次数
        for(int i = 1;i < n;++i)  dp[i] = 100001;
        for(int i = 0;i < n;++i){
            for(int j = i + 1;j <= i + nums[i] && j < n;++j){
                dp[j] = Math.min(dp[j],dp[i] + 1);
            }
        }
        return dp[n-1];
    }
}
以下是优化后的代码。
这个优化的核心思路基于一个观察:DP数组在跳跃游戏问题中是单调递增的。也就是说,位置j的最小跳跃次数不会多于位置j+1的最小跳跃次数。
反向遍历的优势:从i+nums[i]向回遍历到i+1,这样一旦遇到某个j满足dp[j] <= dp[i] + 1,就意味着j以及比j更靠近i的位置都已经获得了比从i跳转过去更优(或相等)的解。既然DP数组是单调的,那么就没有必要继续向更靠近i的位置遍历了。
减少重复计算:你的原始代码中,即使某个位置j已经通过之前的i获得了最小跳跃次数,后续的i仍然会尝试更新它。优化后的代码通过反向遍历和判断条件,显著减少了这类冗余操作。
class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n]; // dp[i]表示到达此处的最小跳跃次数
        for(int i = 1; i < n; i++)  dp[i] = 100001;
        for(int i = 0; i < n; i++) {
            // 关键优化:从最远点向回遍历,遇到已更新位置可提前结束
            for(int j = Math.min(n - 1, i + nums[i]); j > i; j--) {
                // 如果j位置已经是最优解,说明更近的位置也已经更新过
                if(dp[j] <= dp[i] + 1)  break;
                dp[j] = dp[i] + 1;
            }
        }
        return dp[n - 1];
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号