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
Constraints:
1 <= coins.length <= 300
1 <= coins[i] <= 5000
- All the values of
coins
are unique. 0 <= amount <= 5000
- It's a fairly easy question, but it is an excellent introduction to a faily important algorithmic pattern, i.e., Dynamic Programming (DP).
- Assume you worked on DP problems before, you are probably familiar with the concepts likes "base case", "state" and "formula", let's forget about that for now and see how we can achieve that.
- Btw, when you see a statement like "return the number of combinations ...", that's a good signal to try DP first.
- Let's see we can do for this problem.
- So we want to find out how to make
amount
with different uniquecoins
. - Let's take the first example, where
coins = [1,2,5]
andamount = 5
. - So to make a
5
, we can grab a coin5
, that's one way and only way with a coin5
. Easy. - Is there another way to make
5
though? Yep, since we have a coin1
, if we can make a4
inX
number of ways, then we know we can get a5
inX
more number of ways. - Similarly, since we have a coin
2
, if we can make a3
inY
number of ways, we know we can get a5
inY
more number of ways. - I believe you probably spot a pattern now, which is, if we define
dp[amount]
to be "number of ways to getamount
", thendp[amount] = dp[amount] + dp[amount - coin] for coin in coins
. - And how do we get
dp[amount - coin]
? Actually, it's the same question. Assumeamount - coin = i
, we havedp[i] = dp[i] + dp[i - coin] for coin in coins
. - And initially,
dp
should be initialized with all0
s, exceptdp[0] = 1
, because that's what we have at the beginning, so no surprise. - At last we should return
dp[amount]
, that's it. - It should be fairly easy now to write the code. Let me know if it does not make sense to you.
- Thanks for reading, :).
// dp[i]: different ways to make up amount i
// dp[i] = dp[i] + dp[i - coin] for coin in coins
const change = function(amount, coins) {
const dp = Array(amount + 1).fill(0);
dp[0] = 1;
for (const coin of coins) {
for (let i = coin; i <= amount; i += 1) {
dp[i] += dp[i - coin];
}
}
return dp[dp.length - 1];
};