[LeetCode] 746. Min Cost Climbing Stairs 爬樓梯的最小損失


 

On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).

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.

Example 1:

Input: cost = [10, 15, 20]
Output: 15
Explanation: Cheapest is start on cost[1], pay that cost and go to the top.

 

Example 2:

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:

  1. cost will have a length in the range [2, 1000].
  2. 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])

最后返回最后一個數字dp[n]即可,參見代碼如下:

 

解法一:

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 值小的那個,所以遞歸式如下:

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

 

類似題目:

Climbing Stairs

 

參考資料:

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

https://leetcode.com/problems/min-cost-climbing-stairs/discuss/144682/3-Lines-Java-Solution-O(1)-space

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM