Coin Change II
Coin Change II is LeetCode 518 (Medium), also written Coin Change 2. You are given an array coins of distinct denominations and a target amount. Return the number of combinations of coins that add up to exactly amount.
- Each coin can be used any number of times.
- Order does not matter: the same coins in a different order count as one combination.
- If no combination reaches the amount, return 0.
- 1 <= coins.length <= 300
- 1 <= coins[i] <= 5000
- All the values of coins are unique.
- 0 <= amount <= 5000
Intuition
Counting combinations means 2+2+1 and 1+2+2 are the same answer, so the danger is counting one combination several times. The fix is to fix an order: decide how many of the first coin, then the second, and so on. With the coins in a fixed order, each combination has only one way to be built.
When a new coin c joins, the ways to make an amount split cleanly into two groups: those that never use c, which are already counted, and those that use it at least once, which are a way to make the amount minus c with one more c on top. Adding the groups gives the number of ways to make change, each combination counted once.
This is the number of ways to make change problem. Count the ways to reach a total from reusable items where order does not matter. That is the counting form of the unbounded knapsack. The tell is the word combinations: put the items in the outer loop. If the question counted ordered sequences, the amount would go outside instead.
Approach
Before reading on, list by hand the ways to make 5 from [1, 2, 5]. Then try dp[a] += dp[a - c] with the amount loop outside. Why does it give a bigger number?
Two ways to solve it
Keep one array dp[a] and fold the coins in one at a time with dp[a] += dp[a - c].
- Space: a single row of
amount + 1counts. - Speed: the same additions as the table, with less memory.
- Catch: the coin loop must stay outside the amount loop.
This is the optimised version to write in an interview.
Row i counts the ways to make each amount with only the first i coins: skip coin i, or use it once more.
- Space:
n + 1rows ofamount + 1counts. - Speed: the same additions as the 1-D array.
- Readability: every stage of the count stays visible.
The clearest way to see the recurrence before shrinking it.
Each row reads only itself and the row above, so the table collapses into one array with the same answer and the same time. The steps, code and live demo follow the 1-D array, and the 2-D table code is further down.
Define the state
dp[a] = the number of combinations that make amount a using only the coins processed so far. The array has amount + 1 entries and is reused across coins, so each pass upgrades every count to include one more coin type.
Set the base case
dp[0] = 1: there is exactly one way to make 0, the empty combination. Every other entry starts at 0. If dp[0] were 0, nothing could ever be counted.
Loop over coins outside, amounts inside
For each coin c, run a from c to amount and add dp[a] += dp[a - c]. The old dp[a] is the ways without c; dp[a - c], already updated in this pass, is the ways that use c at least once, which is what lets c repeat. Keep the coin loop outside: swapping the loops counts orderings, so 1+2 and 2+1 would both be counted.
Return dp[amount]
After the last coin, dp[amount] holds every combination counted once, since each one was built in the single coin order the loops allow. If no coins can reach the amount, it stays 0, which is the correct answer rather than an error.
Coin Change II solution in Python | C++ | Java
dp[a] = the number of combinations that make amount a. With no coins, only amount 0 can be made, in exactly one way: take nothing. That 1 is what every combination grows from.dp[a] = the number of combinations that make amount a. With no coins, only amount 0 can be made, in exactly one way: take nothing. That 1 is what every combination grows from.dp[a] = the number of combinations that make amount a. With no coins, only amount 0 can be made, in exactly one way: take nothing. That 1 is what every combination grows from.2-D DP table
dp[i][a] counts the combinations that make a from the first i coins. It copies the count from the row above (coin i unused), then adds dp[i][a - c] from its own row (coin i used again).
Common pitfalls
Putting the amount loop outside
for a in range(1, amount + 1):
for c in coins:
if c <= a:
dp[a] += dp[a - c]for c in coins:
for a in range(c, amount + 1):
dp[a] += dp[a - c]With the amount outside, each amount tries every coin as the last one, so 1+2+2, 2+1+2 and 2+2+1 are counted separately. For [1, 2, 5] and 5 it returns 9 instead of 4. That loop order answers Combination Sum IV.
Starting with dp[0] = 0
dp = [0] * (amount + 1)
dp = [1] + [0] * amount
Every combination is built by adding a coin to a smaller combination, and the smallest one is the empty combination for amount 0. Without that 1, every entry stays 0.
Looping the amount downwards
for c in coins:
for a in range(amount, c - 1, -1):
dp[a] += dp[a - c]for c in coins:
for a in range(c, amount + 1):
dp[a] += dp[a - c]Going downwards reads dp[a - c] from before coin c joined, so each coin can be used at most once (0/1 knapsack). Going upwards lets the same coin be reused, which this problem allows.
Edge cases
Return 1: the empty combination. dp[0] = 1 is returned directly.
LeetCode guarantees the answer fits in a signed 32-bit integer, but intermediate entries can be larger. The C++ version uses unsigned long long for safety.
Complexity
Combinations vs permutations vs fewest coins
The same coins and the same dp[a - c] lookup answer three different questions. The loop order and the operation decide which.
| Problem | Counts | Operation | Loop order | [1,2,5], 5 |
|---|---|---|---|---|
| Coin Change II (518) | combinations | dp[a] += dp[a - c] | coins outer | 4 |
| Combination Sum IV (377) | ordered sequences | dp[a] += dp[a - c] | amount outer | 9 |
| Coin Change (322) | fewest coins | dp[a] = min(dp[a], dp[a - c] + 1) | either | 1 (just 5) |
Coin Change II FAQ
What does Coin Change II ask?
It asks how many different combinations of coins, each usable any number of times, add up to the amount. Order does not matter. For coins [1, 2, 5] and amount 5 the answer is 4: 5, 2+2+1, 2+1+1+1, 1+1+1+1+1.
How does the Coin Change II dynamic programming solution count combinations?
- State:
dp[a]= number of combinations that makea. - Base case:
dp[0] = 1. - Recurrence: for each coin
c, forafromcto amount,dp[a] += dp[a - c]. - Why coins outside: coins are added in a fixed order, so each combination is built exactly once.
- Complexity: O(amount × n) time, O(amount) space.
- Example:
[1, 2, 5], 5 gives 4.
Why does the loop order matter in Coin Change II?
With coins outside, a combination is always built in coin order, so it is counted once. With the amount outside, every coin is tried as the last coin at every amount, so each ordering is counted separately. For [1, 2, 5] and 5 that gives 9 instead of 4.
What is the difference between Coin Change and Coin Change II?
Coin Change (322) finds the minimum number of coins, using min. Coin Change II (518) counts the number of combinations, using +=. Both are unbounded knapsack DPs over the amount.
Why is dp[0] equal to 1?
There is exactly one way to make amount 0: choose no coins. Every other combination is that empty combination with coins added, so this 1 is what all the counts are built from.