給定不一樣面額的硬幣 coins
和一個總金額 amount
。編寫一個函數來計算能夠湊成總金額所需的最少的硬幣個數。若是沒有任何一種硬幣組合能組成總金額,返回 -1。
你能夠認爲每種硬幣的數量是無限的。python
coins = [1,2,5] amount = 11 結果:3,硬幣爲:5,5,1
動態規劃解題思路是:將大的問題拆解成小一點問題,小問題和大問題的解決思路是相似的
給定一個總金額11,有三種硬幣:1,2,5。
將問題的規模減小:湊11難湊,就湊10,若是10難湊就湊9,一直到湊1,湊0。算法
添加數組dp,表示湊到某一個數值的最小硬幣數。如dp[1]就表明金額爲1的最少硬幣數,dp[10]就表明金額爲10的最少硬幣數。該dp數組長度爲12,從金額爲0到11,初始化爲:數組
[12,12,12,12,12,12,12,12,12,12,12,12]
之因此初始化爲12,是總金額+1,由於可能會存在湊不到這個數的狀況。當湊不到時,dp[-1]=12,湊獲得時,即便硬幣金額最小爲1,也只用11便可。app
當要湊成的金額爲0時:函數
dp = [0,12,12,12,12,12,12,12,12,12,12,12]
金額爲1時
:
因爲硬幣有 一、二、5,因此,金額大於硬幣1的數額,因此一塊硬幣價值爲1便可code
dp = [0,1,12,12,12,12,12,12,12,12,12,12]
金額爲2時
:
金額爲2是,金額大於硬幣1,硬幣2,因此有兩種方案能夠湊齊。
一、某一個金額加上硬幣2,那麼就是金額0 + 硬幣2 dp[0] = 0,因此dp[2] = 1
二、某一個金額加上硬幣1,那麼就是金額1 + 硬幣1 dp[1] = 1,因此dp[2] = dp[1] + 1 = 2blog
選擇最小的,因此dp[2] = 1數學
dp = [0,1,1,12,12,12,12,12,12,12,12,12]
金額爲3時
:
金額大於硬幣1,硬幣2,因此有兩種方案
某一個金額加上硬幣2,就是 金額1 + 硬幣2 dp[3-2] + 1。dp[3-2],意思就是金額3減去硬幣2,獲得的金額1其最小的組成硬幣數。dp[3] = dp[3-1] + 1 = 2
某一個金額加上硬幣1,就是 金額2 + 硬幣1 dp[3-1] + 2。dp[3-1],意思就是 金額3 - 硬幣1,獲得的金額其最小組成的硬幣數。dp[3] = dp[3-2] + 1 = 2
因此,金額3時,dp[3] = 2class
dp = [0,1,1,2,12,12,12,12,12,12,12,12]
金額爲4時
:
金額大於硬幣1,硬幣2,因此有兩種方案
金額爲2 + 硬幣2,即 dp[4-2] + 1,dp[4] = 2
金額爲3 + 硬幣1,即 dp[4-1] + 1,dp[4] = 3
因此,金額爲4時,dp[4] = 2技巧
dp = [0,1,1,2,2,12,12,12,12,12,12,12]
金額爲5時
:
金額大於硬幣1,硬幣2,硬幣5,因此有三種方案
金額爲4 + 硬幣1,即 dp[5-1] + 1,dp[5] = 2 + 1 = 3
金額爲3 + 硬幣2,即 dp[5-2] + 1,dp[5] = 2 + 1 = 3
金額爲0 + 硬幣5,即 dp[5-5] + 1,dp[5] = 1
因此,dp[5] = 1
dp = [0,1,1,2,2,5,12,12,12,12,12,12]
最終按照這個規律,算出dp全部的數值。
示例 1: 輸入:coins = [1, 2, 5], amount = 11 輸出:3 解釋:11 = 5 + 5 + 1
def coinChange(coins, amount): # 構建dp動態數組 dp = [amount + 1] * (amount + 1) # 初始化 dp[0] = 0 for i in range(1, amount + 1): # 每個金額,全部能湊成的方案的硬幣數,最後取最小值 temp = [dp[i]] for coin in coins: # 當金額大於某一個硬幣時才考慮,不然必定沒法用大額硬幣湊成小額 if i >= coin: temp.append(dp[i-coin]+1) dp[i] = min(temp) print(dp) return -1 if dp[-1] == amount + 1 else dp[-1] coins = [1, 2, 5] amount = 11 res = coinChange(coins, amount) print(res)
動態規劃系列到這一篇就算完結了,我的感受動態規劃是算法中頗有難度,有技巧,有魅力的一種算法。爲了學明白這一種算法,我也不少次在深夜裏思考求解。當我以爲本身彷佛掌握了淺顯的規律以後,就把它記錄下來。這固然是我我的不太成熟的思想,動態規劃的深奧遠不是我能用9篇文章說明白的。可是,但願讀者能從這9篇文章學到一點個人經驗,摸到解決動態規劃問題的門檻。最後用我最喜歡的宮崎駿的動漫大集合做爲本篇的封面。