力扣(LeetCode)45

題目地址:
https://leetcode-cn.com/probl...
題目描述:

給定一個非負整數數組,你最初位於數組的第一個位置。

數組中的每個元素代表你在該位置可以跳躍的最大長度。

你的目標是使用最少的跳躍次數到達數組的最後一個位置。

示例:

輸入: [2,3,1,1,4]
輸出: 2
解釋: 跳到最後一個位置的最小跳躍數是 2。
     從下標爲 0 跳到下標爲 1 的位置,跳 1 步,然後跳 3 步到達數組的最後一個位置。

解答:
第55題一樣,首先試一下動態規劃dp[i]代表到座標爲i的節點所用的最短步驟。
那麼dp[0] = 0,dp[i] = min(dp[i-k]+1) , k >= 0 並且 k <= i-1,並且nums[k]+k >= i。
不過可惜的是複雜度過大,爲O(N²),用例不通過。

換一種思路,這個和第55題一樣,這是個貪心問題,用一個max變量記錄當前能夠到達的最遠節點。那麼初始時
max = nums[0],對於i=1...nums.length-1,如果nums[i]+i > max(即該節點能夠到達比max更遠的節點)
就更新max,並且把dp[max+1]...dp[nums[i]+i]更新爲dp[i]+1否則跳過。這樣一來,每一個節點只計算一次。
也只訪問一次,時間複雜度爲O(N)。

java ac代碼:

class Solution {
    public int jump(int[] nums) {
        
        int[]dp = new int[nums.length];
      
        //用這個最大值代替優先隊列,因爲效果是一樣的
        //用優先隊列保存已經求出的最大下標也可以,但是
        //每次都是從小到大求,所以每次求出更新max即可
        //保持是最大的,不需要使用優先隊列。
        int max = nums[0];
        
        for(int i = 1;i < nums.length && i <= nums[0];i++)
        {
            dp[i] = 1;
        }
        
        for(int i = 1;i < nums.length;i++)
        {
            for(int k = max+1;k < nums.length&&k<=i+nums[i];k++)
            {
                dp[k] = dp[i]+1;
                max = k;
            }
        }
        
        return dp[nums.length-1];
        
    }
}

動態規劃超時代碼:

class Solution {
    public int jump(int[] nums) {
        
        int[] dp = new int[nums.length];
        dp[0] = 0;
        for(int i = 1;i < nums.length;i++)
        {
            int temp = Integer.MAX_VALUE;
            for(int k = i-1;k >= 0;k--)
                if(nums[k] >= i-k)
                    temp = Math.min(temp,dp[k]);
            dp[i] = temp+1;
            
        }
        return dp[nums.length-1];
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章