You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.
Note: You can assume that
- 0 <= amount <= 5000
- 1 <= coin <= 5000
- the number of coins is less than 500
- the answer is guaranteed to fit into 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
給定一些不同面值的硬幣,和一個錢數。編寫函數計算要得到目標金額有多少種不同的硬幣組合方式。
322. Coin Change 的變形,322題是求最少能用幾個硬幣組成給的錢數,而這題求的是組成給定錢數總共有多少種不同的方法。
解法:動態規划DP, 建立dp數組,保存能到達當前amount的步數。逐個金額遍歷,看只用前i個金額能到達j的步數有多少,實現方法是累加起來dp[當前amount - 第i個金額],最后返回dp[amount]。
State: dp[i], 表示總額為i時的方案數
Function: dp[i] = Σdp[i - coins[j]], 表示總額為i時的方案數 = 總額為i-coins[j]的方案數的加和
Initialize: dp[0] = 1, 表示總額為0時方案數為1
Retrun: dp[n] or dp[-1]
Java:
public class Solution {
public int change(int amount, int[] coins) {
if (coins == null || coins.length == 0) {
return amount == 0? 1: 0;
}
int[] dp = new int[amount + 1];
dp[0] = 1;
for (int i = 0; i < coins.length; i ++) {
for (int j = 1; j <= amount; j ++) {
if (j >= coins[i]) {
dp[j] += dp[j - coins[i]];
}
}
}
return dp[amount];
}
}
Python:
class Solution(object):
def change(self, amount, coins):
"""
:type amount: int
:type coins: List[int]
:rtype: int
"""
dp = [0] * (amount + 1)
dp[0] = 1
for c in coins:
for x in range(c, amount + 1):
dp[x] += dp[x - c]
return dp[amount]
擴展思考:將上述代碼中的循環順序對調,即為求不同硬幣的排列數(Permutation)
class Solution(object):
def change(self, amount, coins):
"""
:type amount: int
:type coins: List[int]
:rtype: int
"""
dp = [0] * (amount + 1)
dp[0] = 1
for x in range(amount + 1):
for c in coins:
if c > x: continue
dp[x] += dp[x - c]
return dp[amount]
C++:
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for (int coin : coins) {
for (int i = coin; i <= amount; ++i) {
dp[i] += dp[i - coin];
}
}
return dp[amount];
}
};
類似題目:
[LeetCode] 322. Coin Change 硬幣找零
[CareerCup] 9.8 Represent N Cents 組成N分錢
All LeetCode Questions List 題目匯總
