Leet Code 322-Coin Change

給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。

示例 1:

輸入: coins = [1, 2, 5], amount = 11
輸出: 3
解釋: 11 = 5 + 5 + 1
示例 2:

輸入: coins = [2], amount = 3
輸出: -1
說明:
你可以認爲每種硬幣的數量是無限的。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/coin-change
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

思路一:暴力法

思路二:貪心法

每次都用較大面額的硬幣去湊

可能會出錯比如給定 coins = [1, 6, 7], amount = 30, 使用貪心的話
res = 6, 47 + 21
而實際使用 5 個6元的硬幣即可

思路三:DP

硬幣問題跟爬樓梯問題有異曲同工之妙,可以想象成給定每次爬樓梯的步數和樓梯的階數,求最少多少步可以爬完樓梯,類似地,DP兩步走起~

  1. 定義狀態方程
    DP[i]: 表示 i 階臺階,最少的步數

  2. 狀態轉移方程
    DP[i] = min{DP[i-steps[j]]} + 1, j: 0 -> len(steps)-1
    且有初始狀態 DP[0] = 0

碼代碼的時候注意是基於 DP[0], 從 DP[1] 開始形成整個 DP 數組,每次更新 DP[i] 時注意隱形條件:i >= step[j]
還有就是注意異常情況咯,見代碼

class Solution:
    def coinChange(self, coins, amount) -> int:
        if not coins or amount < 0: return -1

        dp = [0] + [float("inf") for _ in range(amount)]
        for i in range(len(dp)):
            for coin in coins:
                dp[i] = min(dp[i-coin] + 1, dp[i]) if i >= coin else dp[i]
        return dp[-1] if dp[-1] != float("inf") else -1

思路三:完全揹包

仔細想想,該問題跟完全揹包問題也有些神似,可以理解爲 amount 爲揹包體積,coins 爲物品的體積,所求即剛好裝滿揹包的狀態下,所需最少的物品數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章