###### tags: `Leetcode` `medium` `dynamic programming` `python` `c++` # 518. Coin Change II ## [題目連結:] https://leetcode.com/problems/coin-change-ii/description/ ## 題目: You are given an integer array ```coins``` representing coins of different denominations and an integer ```amount``` representing a total amount of money. Return the number of combinations that make up that amount. If that amount of money cannot be made up by any combination of the coins, return ```0```. You may assume that you have an infinite number of each kind of coin. The answer is **guaranteed** to fit into a signed **32-bit** integer. **Example 1:** ``` Input: amount = 5, coins = [1,2,5] Output: 4 Explanation: there are four ways to make up the amount: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1 ``` **Example 2:** ``` Input: amount = 3, coins = [2] Output: 0 Explanation: the amount of 3 cannot be made up just with coins of 2. ``` **Example 3:** ``` Input: amount = 10, coins = [10] Output: 1 ``` ## 解題想法: * 此題為給定不同面額的錢幣與一個總金額,假設每一種面額的錢幣有無限個 * 求出可湊成總金額的組合數 * 使用DP: * 定義**dp[i]: 金額為i的組合數** * 初始: * dp[0]=1 * 0元: 完全不拿1種選擇 * 本題關鍵: * **第一圈迴圈: 錢幣的種類** * 第二圈迴圈: * 調整dp[i] * 動態方程式: * **dp[i]+=dp[i-value]** (for value in coins) * 說明: * 前 i 種硬幣湊出 amount 元的方法 = 前 i - 1 種硬幣湊出 amount 元的方法 + 前 i 種硬幣湊出 amount - value 元的方法 * 其中 value 為第 i 種硬幣的面額。 * trace如下: ``` ex: amount 0 1 2 3 4 5 coin: 1 1 1 1 1 1 1 (1)+2 1 1 2 2 3 3 (12)5 1 1 2 2 3 4 ``` * 說明可能有點籠統: 詳細可參考大神[https://vrabe.tw/blog/leetcode-518-coin-change-2 ## Python: ``` python= class Solution(object): def change(self, amount, coins): """ :type amount: int :type coins: List[int] :rtype: int """ #dp[i]:金額為i的組合數 dp=[0]*(amount+1) dp[0]=1 #0元 都不拿1種選擇 for value in coins: #錢的種類 #從value開始往後 #因為若當前i比value小 直接繼承之前的dp[i]就好 不用更動 for i in range(value,amount+1): dp[i]+=dp[i-value] return dp[amount] result=Solution() amount = 5 coins = [1,2,5] ans=result.change(amount,coins) print(ans) ``` ## C++: ``` cpp= class Solution { public: int change(int amount, vector<int>& coins) { vector<int> dp(amount+1, 0); dp[0]=1; for (int value: coins){ for (int i=value; i<amount+1; ++i){ dp[i]+=dp[i-value]; } } return dp[amount]; } }; ```