題目描述:給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。(你可以認為每種硬幣的數量是無限的。)
解法:動態規划
對於一個金額,與它的差值為硬幣庫(coins)中硬幣面值的數都是它一步就可以到達的,這里一步到達是指只需要一個硬幣就能解決。因此,對於一個金額,能夠滿足題目要求的硬幣數為所有能夠一步到達這個它的金額所需的硬幣數加1。
dp[i] = 1+ min (dp[i-coins[0]], dp[i-coins[1]]......)
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float("inf") for i in range(amount+1)] #初始化dp數組
dp[0] = 0 # 當amount=0時,硬幣所需數為0
for i in range(1, amount + 1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i], dp[i - coin] + 1)
if dp[-1] == float("inf"):
return -1
else:
return dp[-1]
類型二:找出最少的硬幣——組成所有的面值
這題其實是2019年騰訊開發崗實習生筆試的第一題~
題目描述:給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成[1, amount]中所有面值所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。(你可以認為每種硬幣的數量是無限的。
這種情況比上面情況稍微復雜一點,因為要組成所有范圍內的面值。如圖所示:
代碼如下:
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float("inf") for i in range(amount+1)] #初始化dp數組
dp[0] = 0 # 當amount=0時,硬幣所需數為0
if 1 not in coins: # 如果硬幣里面沒有面值為1的硬幣,則無法組成所有的硬幣
return -1
dp[1] = 1
for i in range(2,amount+1):
min_ = dp[i]
for j in range(1,i):
if j in coins and j<=i-j+1: # 如果另一部分直接可以用一個硬幣代替
min_ = min(min_, dp[i-j]+1)
else:
min_ = min(min_,dp[i-j]+dp[j])
dp[i]=min_
return dp[-1]