LeetCode算法45:跳躍遊戲 II

問題
給定一個非負整數數組,你最初位於數組的第一個位置。
數組中的每個元素代表你在該位置可以跳躍的最大長度。
你的目標是使用最少的跳躍次數到達數組的最後一個位置。

示例:
輸入: [2,3,1,1,4]
輸出: 2
解釋: 跳到最後一個位置的最小跳躍數是 2。
從下標爲 0 跳到下標爲 1 的位置,跳 1 步,然後跳 3 步到達數組的最後一個位置。
說明:
假設你總是可以到達數組的最後一個位置。

思考
該題思路比較怪異,很難想到,不過可以作爲知識儲備,記下這種求解方式。以後遇到類似問題可以算是提供一個思路。

看示例:
[2,3,1,1,4]
我們從後往前推,最終目的是要跳到最後一個位置,即4的位置。但是這裏的數字並沒有意義。
對於第4個數1,需要跳一次;
對於第3個數1,顯然只能跳到第4個數上,那麼從第3個數開始跳到最後需要兩次;
對於第2個數3,顯然一步到位,跳一次;
對於第一個數2,只能選擇跳一次還是跳兩次,顯然選擇跳一次的收益更大,最終只需跳兩次;

倒推時發現滿足
①最優子結構,②重疊子問題。可以使用動態規劃。

狀態描述:f[i]表示在第i個位置最小需要幾次可跳到最後一個位置
狀態轉移方程:f[i] = min(f[i+1]~f[i+nums[i]])+1
初始條件f[nums.length()-1]=0

對狀態轉移方程的說明:
在第i個位置上的數據,通過1步可以跳到下一個位置f(i+1)上,但是同時其具有選擇跳nums[i]的機會,所以這裏的最小值,是遍歷其後1~nums個數量上的最小值,誰最小,就跳到哪個上面。

代碼

class Solution {
    public int jump(int[] nums) {
        int f[] = new int[nums.length];
        if (nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return 0;
        }
        f[nums.length - 1] = 0;
        for (int i = nums.length - 2; i >= 0; i--) {
            f[i] = findMin(f, i, nums[i]) + 1;
            if (f[i] < 0) f[i] = Integer.MAX_VALUE;
        }

        return f[0];

    }

    private int findMin(int[] f, int i, int num) {
        int min = Integer.MAX_VALUE;
        for (int j = 1; j <= num && i + j < f.length; j++) {
            min = Math.min(min, f[i + j]);//此處是查看從此處向後可以選擇的值的範圍,查找到最小值。本步驟的+1次跳躍在前面循環中增加;
        }
        return min;
    }
}

參考:
https://www.cnblogs.com/acbingo/p/9350223.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章