On a staircase, the i
-th step has some non-negative cost cost[i]
assigned (0 indexed).javascript
Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the floor, and you can either start from the step with index 0, or the step with index 1.html
Example 1:java
Input: cost = [10, 15, 20] Output: 15 Explanation: Cheapest is start on cost[1], pay that cost and go to the top.
Example 2:git
Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] Output: 6 Explanation: Cheapest is start on cost[0], and only step on 1s, skipping cost[3].
Note:github
cost
will have a length in the range[2, 1000]
.- Every
cost[i]
will be an integer in the range[0, 999]
.
這道題應該算是以前那道 Climbing Stairs 的拓展,這裏不是求步數,而是每一個臺階上都有一個 cost,讓咱們求爬到頂端的最小 cost 是多少。換湯不換藥,仍是用動態規劃 Dynamic Programming 來作。這裏定義一個一維的 dp數組,其中 dp[i] 表示爬到第i層的最小 cost,而後來想 dp[i] 如何推導。來思考一下如何才能到第i層呢?是否是隻有兩種可能性,一個是從第 i-2 層上直接跳上來,一個是從第 i-1 層上跳上來。不會再有別的方法,因此 dp[i] 只和前兩層有關係,能夠寫作以下:數組
dp[i] = min(dp[i- 2] + cost[i - 2], dp[i - 1] + cost[i - 1])post
最後返回最後一個數字dp[n]便可,參見代碼以下:優化
解法一:spa
class Solution { public: int minCostClimbingStairs(vector<int>& cost) { int n = cost.size(); vector<int> dp(n + 1); for (int i = 2; i < n + 1; ++i) { dp[i] = min(dp[i- 2] + cost[i - 2], dp[i - 1] + cost[i - 1]); } return dp.back(); } };
再來看一種 DP 的解法,跟上面的解法很相近,不一樣在於 dp 數組長度爲n,其中 dp[i] 表示到第 i+1 層的最小 cost,分別初始化 dp[0] 和 dp[1] 爲 cost[0] 和 cost[1]。而後從 i=2 處開始遍歷,此時更新思路是,要爬當前的臺階,確定須要加上當前的 cost[i],那麼仍是要從前一層或者前兩層的臺階上跳上來,選擇 dp 值小的那個,因此遞歸式以下:code
dp[i] = cost[i] + min(dp[i- 1], dp[i - 2])
最後在最後兩個dp值中選擇一個較小的返回便可,參見代碼以下:
解法二:
class Solution { public: int minCostClimbingStairs(vector<int>& cost) { int n = cost.size(); vector<int> dp(n); dp[0] = cost[0]; dp[1] = cost[1]; for (int i = 2; i < n; ++i) { dp[i] = cost[i] + min(dp[i- 1], dp[i - 2]); } return min(dp[n - 1], dp[n - 2]); } };
咱們能夠對空間複雜度進行優化,經過前面的分析咱們能夠發現,當前的 dp 值僅僅依賴前面兩個的值,因此沒必要把整個 dp 數組都記錄下來,只需用兩個變量a和b來記錄前兩個值,而後不停的用新獲得的值來覆蓋它們就行了。初始化a和b均爲0,而後遍歷 cost 數組,首先將a和b中較小值加上 num 放入臨時變量t中,而後把b賦給a,把t賦給b便可,參見代碼以下:
解法三:
class Solution { public: int minCostClimbingStairs(vector<int>& cost) { int a = 0, b = 0; for (int num : cost) { int t = min(a, b) + num; a = b; b = t; } return min(a, b); } };
咱們還能夠用遞歸來寫,須要優化計算量,即用 HashMap 來保存已經算過了臺階,用的仍是 dp 的思想,參見代碼以下:
解法四:
class Solution { public: int minCostClimbingStairs(vector<int>& cost) { unordered_map<int, int> memo; return helper(cost, cost.size(), memo); } int helper(vector<int>& cost, int i, unordered_map<int, int>& memo) { if (memo.count(i)) return memo[i]; if (i <= 1) return memo[i] = cost[i]; return memo[i] = (i == cost.size() ? 0 : cost[i]) + min(helper(cost, i - 1, memo), helper(cost, i - 2, memo)); } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/746
相似題目:
參考資料:
https://leetcode.com/problems/min-cost-climbing-stairs/
https://leetcode.com/problems/min-cost-climbing-stairs/discuss/110109/c-o1-space
https://leetcode.com/problems/min-cost-climbing-stairs/discuss/110111/javascript-and-c-solutions