成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

數據結構與算法之使用最小花費爬樓梯

開發 后端 算法
數組的每個下標作為一個階梯,第 i 個階梯對應著一個非負數的體力花費值 cost[i](下標從 0 開始)。

[[443068]]

使用最小花費爬樓梯

力扣題目鏈接:https://leetcode-cn.com/problems/min-cost-climbing-stairs

數組的每個下標作為一個階梯,第 i 個階梯對應著一個非負數的體力花費值 cost[i](下標從 0 開始)。

每當你爬上一個階梯你都要花費對應的體力值,一旦支付了相應的體力值,你就可以選擇向上爬一個階梯或者爬兩個階梯。

請你找出達到樓層頂部的最低花費。在開始時,你可以選擇從下標為 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] 將會是一個整型數據,范圍為 [0, 999] 。

思路

這道題目可以說是昨天動態規劃:爬樓梯的花費版本。

注意題目描述:每當你爬上一個階梯你都要花費對應的體力值,一旦支付了相應的體力值,你就可以選擇向上爬一個階梯或者爬兩個階梯

所以示例1中只花費一個15 就可以到階梯頂,最后一步可以理解為 不用花費。

讀完題大家應該知道指定需要動態規劃的,貪心是不可能了。

確定dp數組以及下標的含義

使用動態規劃,就要有一個數組來記錄狀態,本題只需要一個一維數組dp[i]就可以了。

dp[i]的定義:到達第i個臺階所花費的最少體力為dp[i]。(注意這里認為是第一步一定是要花費)

對于dp數組的定義,大家一定要清晰!

確定遞推公式

可以有兩個途徑得到dp[i],一個是dp[i-1] 一個是dp[i-2]。

那么究竟是選dp[i-1]還是dp[i-2]呢?

一定是選最小的,所以dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i];

注意這里為什么是加cost[i],而不是cost[i-1],cost[i-2]之類的,因為題目中說了:每當你爬上一個階梯你都要花費對應的體力值

dp數組如何初始化

根據dp數組的定義,dp數組初始化其實是比較難的,因為不可能初始化為第i臺階所花費的最少體力。

那么看一下遞歸公式,dp[i]由dp[i-1],dp[i-2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就夠了,其他的最終都是dp[0]dp[1]推出。

所以初始化代碼為:

  1. vector<int> dp(cost.size()); 
  2. dp[0] = cost[0]; 
  3. dp[1] = cost[1]; 

確定遍歷順序

最后一步,遞歸公式有了,初始化有了,如何遍歷呢?

本題的遍歷順序其實比較簡單,簡單到很多同學都忽略了思考這一步直接就把代碼寫出來了。

因為是模擬臺階,而且dp[i]又dp[i-1]dp[i-2]推出,所以是從前到后遍歷cost數組就可以了。

但是稍稍有點難度的動態規劃,其遍歷順序并不容易確定下來。

例如:01背包,都知道兩個for循環,一個for遍歷物品嵌套一個for遍歷背包容量,那么為什么不是一個for遍歷背包容量嵌套一個for遍歷物品呢?以及在使用一維dp數組的時候遍歷背包容量為什么要倒敘呢?

這些都是遍歷順序息息相關。當然背包問題后續「代碼隨想錄」都會重點講解的!

舉例推導dp數組

拿示例2:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] ,來模擬一下dp數組的狀態變化,如下:

使用最小花費爬樓梯

如果大家代碼寫出來有問題,就把dp數組打印出來,看看和如上推導的是不是一樣的。

以上分析完畢,整體C++代碼如下:

  1. // 版本一 
  2. class Solution { 
  3. public
  4.     int minCostClimbingStairs(vector<int>& cost) { 
  5.         vector<int> dp(cost.size()); 
  6.         dp[0] = cost[0]; 
  7.         dp[1] = cost[1]; 
  8.         for (int i = 2; i < cost.size(); i++) { 
  9.             dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; 
  10.         } 
  11.         // 注意最后一步可以理解為不用花費,所以取倒數第一步,第二步的最少值 
  12.         return min(dp[cost.size() - 1], dp[cost.size() - 2]); 
  13.     } 
  14. }; 
  • 時間復雜度:
  • 空間復雜度:

還可以優化空間復雜度,因為dp[i]就是由前兩位推出來的,那么也不用dp數組了,C++代碼如下:

  1. // 版本二 
  2. class Solution { 
  3. public
  4.     int minCostClimbingStairs(vector<int>& cost) { 
  5.         int dp0 = cost[0]; 
  6.         int dp1 = cost[1]; 
  7.         for (int i = 2; i < cost.size(); i++) { 
  8.             int dpi = min(dp0, dp1) + cost[i]; 
  9.             dp0 = dp1; // 記錄一下前兩位 
  10.             dp1 = dpi; 
  11.         } 
  12.         return min(dp0, dp1); 
  13.     } 
  14. }; 
  • 時間復雜度:
  • 空間復雜度:

當然我不建議這么寫,能寫出版本一就可以了,直觀簡潔!

在后序的講解中,可能我會忽略這種版本二的寫法,大家只要知道有這么個寫法就可以了哈。

拓展

這道題描述也確實有點魔幻。

題目描述為:每當你爬上一個階梯你都要花費對應的體力值,一旦支付了相應的體力值,你就可以選擇向上爬一個階梯或者爬兩個階梯。

示例1:

輸入:cost = [10, 15, 20] 輸出:15

從題目描述可以看出:要不是第一步不需要花費體力,要不就是第最后一步不需要花費體力,我個人理解:題意說的其實是第一步是要支付費用的!。因為是當你爬上一個臺階就要花費對應的體力值!

所以我定義的dp[i]意思是也是第一步是要花費體力的,最后一步不用花費體力了,因為已經支付了。

當然也可以樣,定義dp[i]為:第一步是不花費體力,最后一步是花費體力的。

所以代碼這么寫:

  1. class Solution { 
  2. public
  3.     int minCostClimbingStairs(vector<int>& cost) { 
  4.         vector<int> dp(cost.size() + 1); 
  5.         dp[0] = 0; // 默認第一步都是不花費體力的 
  6.         dp[1] = 0; 
  7.         for (int i = 2; i <= cost.size(); i++) { 
  8.             dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); 
  9.         } 
  10.         return dp[cost.size()]; 
  11.     } 
  12. }; 

這么寫看上去比較順,但是就是感覺和題目描述的不太符。哈哈,也沒有必要這么細扣題意了,大家只要知道,題目的意思反正就是要不是第一步不花費,要不是最后一步不花費,都可以。

總結

大家可以發現這道題目相對于 昨天的動態規劃:爬樓梯有難了一點,但整體思路是一樣。

從動態規劃:斐波那契數到 動態規劃:爬樓梯再到今天這道題目,錄友們感受到循序漸進的梯度了嘛。

每個系列開始的時候,都有錄友和我反饋說題目太簡單了,趕緊上難度,但也有錄友和我說有點難了,快跟不上了。

其實我選的題目都是有目的性的,就算是簡單題,也是為了練習方法論,然后難度都是梯度上來的,一環扣一環。

但我也可以隨便選來一道難題講唄,這其實是最省事的,不用管什么題目順序,看心情找一道就講。

難的是把題目按梯度排好,循序漸進,再按照統一方法論把這些都串起來,哈哈,所以大家不要催我哈,按照我的節奏一步一步來就行啦。

學算法,認準「代碼隨想錄」,沒毛病!

其他語言版本

Java

  1. class Solution { 
  2.     public int minCostClimbingStairs(int[] cost) { 
  3.         if (cost == null || cost.length == 0) { 
  4.             return 0; 
  5.         } 
  6.         if (cost.length == 1) { 
  7.             return cost[0]; 
  8.         } 
  9.         int[] dp = new int[cost.length]; 
  10.         dp[0] = cost[0]; 
  11.         dp[1] = cost[1]; 
  12.         for (int i = 2; i < cost.length; i++) { 
  13.             dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]; 
  14.         } 
  15.         //最后一步,如果是由倒數第二步爬,則最后一步的體力花費可以不用算 
  16.         return Math.min(dp[cost.length - 1], dp[cost.length - 2]); 
  17.     } 

Python

  1. class Solution: 
  2.     def minCostClimbingStairs(self, cost: List[int]) -> int
  3.         dp = [0] * (len(cost)) 
  4.         dp[0] = cost[0] 
  5.         dp[1] = cost[1] 
  6.         for i in range(2, len(cost)): 
  7.             dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] 
  8.         return min(dp[len(cost) - 1], dp[len(cost) - 2]) 

Go

  1. func minCostClimbingStairs(cost []intint { 
  2.  dp := make([]int, len(cost)) 
  3.  dp[0], dp[1] = cost[0], cost[1] 
  4.  for i := 2; i < len(cost); i++ { 
  5.   dp[i] = min(dp[i-1], dp[i-2]) + cost[i] 
  6.  } 
  7.  return min(dp[len(cost)-1], dp[len(cost)-2]) 
  8.  
  9. func min(a, b intint { 
  10.  if a < b { 
  11.   return a 
  12.  } 
  13.  return b 

 Javascript

  1. var minCostClimbingStairs = function(cost) { 
  2.     const dp = [ cost[0], cost[1] ] 
  3.  
  4.     for (let i = 2; i < cost.length; ++i) { 
  5.         dp[i] = Math.min(dp[i -1] + cost[i], dp[i - 2] + cost[i]) 
  6.     } 
  7.  
  8.     return Math.min(dp[cost.length - 1], dp[cost.length - 2]) 
  9. }; 

 

責任編輯:姜華 來源: 代碼隨想錄
相關推薦

2021-11-04 09:59:03

動態規劃策略

2021-12-29 11:32:38

數據結構算法爬樓梯

2020-12-31 05:31:01

數據結構算法

2020-10-30 09:56:59

Trie樹之美

2022-09-26 07:56:53

AVL算法二叉樹

2022-09-21 07:57:33

二叉搜索樹排序二叉樹

2020-10-21 14:57:04

數據結構算法圖形

2023-03-08 08:03:09

數據結構算法歸并排序

2020-10-12 11:48:31

算法與數據結構

2020-10-20 08:14:08

算法與數據結構

2023-10-27 07:04:20

2022-01-18 19:13:52

背包問題數據結構算法

2021-09-29 18:28:41

數據結構算法最小生成樹

2009-08-11 14:51:11

C#數據結構與算法

2021-07-16 04:57:45

Go算法結構

2021-12-08 11:31:43

數據結構算法合并區間

2021-12-10 11:27:59

數據結構算法單調遞增的數字

2021-12-21 11:39:01

數據結構算法同構字符串

2009-08-11 14:43:42

C#數據結構與算法

2023-03-10 08:07:39

數據結構算法計數排序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美成人精品 | 日韩国产精品一区二区三区 | 一区二区三区高清 | 69精品久久久久久 | www.亚洲精品 | 五月槐花香 | 少妇一级淫片aaaaaaaaa | 久久国 | 四虎永久在线精品免费一区二 | 欧美一区成人 | 国产农村妇女精品一二区 | 中文字幕日韩欧美 | 一级黄色短片 | 国产我和子的乱视频网站 | 欧美成年网站 | 久久久999精品 | 色婷婷亚洲一区二区三区 | 日韩欧美国产一区二区三区 | 精品视频在线免费观看 | 九九综合 | 91久久综合 | 国产高清一区二区三区 | 精品欧美乱码久久久久久1区2区 | 国产精品日本一区二区在线播放 | 超碰激情 | 国产欧美精品在线观看 | 国产成人综合在线 | 91影院在线观看 | 久久久国产一区二区三区 | 久久影院一区 | 91国内视频在线 | 色婷婷av99xx| 中文字幕亚洲一区二区三区 | 人人看人人干 | 日批的视频 | 亚洲一区二区在线视频 | 午夜精品一区二区三区在线视频 | 国产成人在线一区 | 天天综合天天 | 羞羞视频网站在线观看 | 亚洲精品456 |