leetcode:使用最小花費爬樓梯

題目來源:力扣

題目介紹:

數組的每個索引做爲一個階梯,第 i個階梯對應着一個非負數的體力花費值 costi
每當你爬上一個階梯你都要花費對應的體力花費值,然後你可以選擇繼續爬一個階梯或者爬兩個階梯。
您需要找到達到樓層頂部的最低花費。在開始時,你可以選擇從索引爲 0 或 1 的元素作爲初始階梯。
=========================================================
示例 1:
輸入: cost = [10, 15, 20]
輸出: 15
解釋: 最低花費是從cost[1]開始,然後走兩步即可到階梯頂,一共花費15。
示例 2:
輸入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
輸出: 6
解釋: 最低花費方式是從cost[0]開始,逐個經過那些1,跳過cost[3],一共花費6。
注意:
cost 的長度將會在 [2, 1000]。
每一個 cost[i] 將會是一個Integer類型,範圍爲 [0, 999]。
=======================================================

審題:

該題目是一道較簡單的動態規劃類問題, 但由於一開始沒有選好狀態變量,導致想了好一會而.

首先, 對於該爬樓梯問題,我們可以選擇剩餘第一個樓梯級數作爲狀態變量, 我們可以選擇登上該級樓梯, 也可以選擇不登上該級樓梯, 由於是否登上當前階梯決定是我們是否需要登上下一級樓梯, 因此我們添加一個額外的狀態變量表示是否登上當前樓梯. 我們使用S[i][0]表示當前剩餘第一個樓梯爲i級時, 登上該樓梯的最小花費, S[i][1]表示如果不登上當前樓梯的最小花費. 如果我們沒有踏上當前樓梯, 則我們只能踏上下一級樓梯(最多一次跨上兩級).則我們可以得到如下狀態轉移方程:
S[i][0]=cost[i]+min{S[i+1][0],S[i+1][1]}S[i][0] = cost[i] + min\{S[i+1][0], S[i+1][1]\}
S[i][1]=S[i+1][0]S[i][1] = S[i+1][0]

實際上, 由於當前的選擇爲二元選擇, 我們可以簡化當前最優子結構.對於該爬樓梯問題, 我們選擇剩餘第一個樓梯級數作爲狀態變量,在我們登上該級樓梯後, 我們可以選擇跨一步登上下一級級樓梯, 也可以選擇跨兩步登上下下一級樓梯. 我們使用S[i]表示當前剩餘第一個樓梯爲i級時, 我們登上第i級樓梯的最少花費. 此時我們可以得到如下狀態轉移方程:
S[i]=cost[i]+min{S[i+1],S[i+2]}S[i] = cost[i] + min\{S[i+1], S[i+2]\}.
此時的basecase爲S[cost.length1]=cost[cost.length1]S[cost.length-1] = cost[cost.length-1],
S[cost.length2]=cost[cost.length2]S[cost.length-2] = cost[cost.length-2];

代碼實現如下:

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] S = new int[cost.length];
        //basecase
        S[cost.length-1] = cost[cost.length-1]; 
        S[cost.length-2] = cost[cost.length-2];`在這裏插入代碼片`
        
        for(int i = cost.length-3; i >= 0; i--){
            S[i] = cost[i] + Math.min(S[i+1], S[i+2]);
        }

        return Math.min(S[0], S[1]);
    }
}

由於當前狀態僅有其後續的兩個狀態相關, 因此, 我們可以考慮進行狀態壓縮, 將空間複雜度由O(N)降低到O(1)

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] S = new int[3];
        S[(cost.length-2) % 3] = cost[cost.length-2];
        S[(cost.length-1) % 3] = cost[cost.length-1];

        for(int i = cost.length-3; i >= 0; i--){
            S[i % 3] = cost[i] + Math.min(S[(i+1) % 3], S[(i+2) % 3]);
        }

        return Math.min(S[0], S[1]);
    }
}

如果原數組允許改變, 我們可以直接更改原數組, 而無需使用額外空間.

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