爬樓梯
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是乙個正整數。
輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1. 1 階 + 1 階 + 1 階
2. 1 階 + 2 階
3. 2 階 + 1 階
不難發現,對於要抵達的第n階台階,有兩種方式可以抵達。
在第 (i−1) 階後向上爬 1 階。
在第 (i-2) 階後向上爬 2 階。
得出狀態轉移方程為
dp[i]=dp[i−1]+dp[i−2]
因此可以得出**如下:
func climbstairs(n int) int
dp := make(int, n+1)
dp[1] = 1
dp[2] = 2
for i := 3; i <= n; i++
return dp[n]
}
拓展:如果每次我可以爬 1 或 3 或 5 個台階,這時候有多少種方式可以抵達呢?
原理和每次邁1或2步的時候是一樣的,我們就在內部迴圈可以邁的台階,進行計算有多少種抵達方式。**如下:
func climbstairs(n int) int
dp := make(int, n+1)
step := int
dp[0] = 1
for i := 1; i <= n; i++
} }return dp[n]
}
硬幣組合問題
給定數量不限的硬幣,幣值為25分、10分、5分和1分,編寫**計算n分有幾種表示法。
輸入: n = 10
輸出:4
解釋: 有四種方式可以湊成總金額:
10=10
10=5+5
10=5+1+1+1+1+1
10=1+1+1+1+1+1+1+1+1+1
仔細思考一下,硬幣組合問題和爬樓梯問題其實是極其相似的。比如對於給定n = 6的情況下,我們可以從兩種情況抵達:
從 n = 5 的情況下加乙個1分硬幣
在 n = 1 的情況下加乙個5分硬幣
乍一看,**完全應該和上面是一樣的嘛!但是如果直接使用上面的**去計算,會發現最後得出的結果比預料的要多。可以嘗試下執行爬樓梯拓展中的**,計算n=6的情況。為什麼?
還是以 n = 6 的情況進行舉例
在爬樓梯問題中,先上1步再上5步([1,5]) 和 先上5步再上1步([5,1]) 是2個不同的情況。
在硬幣組合問題中,[1,5] 和 [5,1]屬於同乙個解決方案,都只是使用了乙個1分硬幣乙個5分硬幣。
即硬幣組合問題中,硬幣的排列順序不會產生不同的解決方案。
那麼如何避免硬幣的順序對結果造成的影響呢?答案就是:調換遍歷順序,先遍歷硬幣,保證在考慮一種硬幣的時候沒有其它大面額硬幣的影響,保證解決方案中始終是小硬幣在前大硬幣在後。避免重複計算問題,同樣在n=6的情況下,解決方案計算只有[1,1,1,1,1,1]和[1,5] 兩種。
**:
func waystochange(n int) int
dp := make(int, n+1)
coin := int
dp[0] = 1
for i := 0; i < len(coin); i++
} }return dp[n]
}
爬樓梯問題 動態規劃
題目 乙個人每次只能走一層樓梯或者兩層樓梯,問走到第80層樓梯一共有多少種方法。解題思想 設走第i層樓梯需要dp i 中方法,走第i 1層樓梯需要dp i 1 中方法。則走第 i 1層樓梯的方法種數為dp i 1 dp i 種。實動態規劃解題的主要思想就是找出遞推式,然後利用子問題的解來求最後的最優...
動態規劃(爬樓梯問題)
問題 有 n 階台階,每次可以走 1 或 2 步,請問走到第 n 階台階一共有多少種走法?解 設有 f n 種走法 第一步 1 2 第二步 f n 1 f n 2 狀態方程 f n f n 1 f n 2 n 2 f 0 0,f 1 1,f 2 2 函式 int function int n int...
動態規劃 爬樓梯
假設你正在爬樓梯,需要n步你才能到達頂部。但每次你只能爬一步或者兩步,你能有多少種不同的方法爬到樓頂部?比如n 3,1 1 1 1 2 2 1 3,共有3種不同的方法 返回 3 解題思路 沒接觸過動態規劃的時候,我用排列組合做的,在我這篇部落格中 可以看一下。實際上,這個題目就是乙個斐波那契數列,這...