Browse curriculum

Coin Change II

Count the combinations of coins that make an amount with a 1D DP, looping over coins outside so each combination is counted once.

Problem Understanding

Coin Change II: given an amount and coin values, return the number of combinations that add up to the amount. Each coin can be used any number of times, and order does not matter.

Example: amount = 5, coins = [1, 2, 5] returns 4: 5, 2+2+1, 2+1+1+1, 1+1+1+1+1.

The Intuition: Add One Coin Type at a Time

Let dp[a] be the number of ways to make a using the coin types seen so far. Start with no coins: only dp[0] = 1.

Now allow one more coin type, c. A combination for amount a either uses no c (already counted in dp[a]) or uses at least one, leaving a − c to make with the same coins, c included. So:

  • dp[a] += dp[a − c] for a from c up to amount.

Because one coin type is finished before the next starts, every combination is built in the same coin order, and nothing is counted twice. Swap the two loops and you count ordered sequences instead: that is Combination Sum IV. For the fewest coins rather than the number of ways, see Coin Change.

Interactive Walkthrough

The coins are on top, with the one being added marked. Below, each coin sweeps the dp row left to right: a is marked, and the cell it adds, dp[a − coin], is shaded. Every new coin makes the counts grow again.

Dry Run Table

Input: amount = 5, coins = [1, 2, 5]

After coin dp[0] dp[1] dp[2] dp[3] dp[4] dp[5]
(none) 1 0 0 0 0 0
1 1 1 1 1 1 1
2 1 1 2 2 3 3
5 1 1 2 2 3 4

The Solution Template

Unbounded knapsack counting combinations: coins outside, amounts inside, ascending.

Coin Change II Code
1var change = function(amount, coins) {
2 const dp = new Array(amount + 1).fill(0);
3 dp[0] = 1;
4 for (const coin of coins) {
5 for (let a = coin; a <= amount; a++) {
6 dp[a] += dp[a - coin];
7 }
8 }
9 return dp[amount];
10};

Edge Cases & Common Mistakes

  • amount = 0: the answer is 1, the empty combination.
  • Swapping the loops: amounts outside counts orders, giving 7 instead of 4 for amount 4 with coins [1, 2, 3].
  • Overflow in C and C++: intermediate counts for amounts the answer never uses can exceed 32 bits; an unsigned 64-bit row avoids the overflow error, and the final answer fits in an int.
  • Unreachable amount: dp[amount] simply stays 0, as with amount 3 and coins [2].

Summary

dp[a] counts the combinations that make a. Start from dp[0] = 1, then add coins one at a time with dp[a] += dp[a − coin] for a ascending from the coin. Coins on the outside means each combination is counted once. O(amount · coins) time, O(amount) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Set the base case

    dp[0] = 1: there is one way to make 0, using no coins.

  2. Add coins one at a time

    For each coin, for a from coin to amount, add dp[a − coin] to dp[a].

  3. Read the answer

    Return dp[amount].

Frequently asked questions

Why must the coin loop be on the outside?

With coins outside, every combination is built in coin order: all the 1s, then the 2s, and so on. So 1+2 and 2+1 are the same path and are counted once. With amounts outside, each amount can end with any coin, which counts every order separately, as Combination Sum IV does.


How is this different from Coin Change (LeetCode 322)?

Coin Change asks for the fewest coins, so dp[a] is a minimum over coins. Coin Change II asks how many combinations there are, so dp[a] is a sum. Both can use each coin any number of times.


Why does the inner loop go up from the coin, not down?

Each coin can be used unlimited times. Going up, dp[a − coin] may already include this coin, which is exactly what lets it be used again. Going down would allow it at most once, as in 0/1 knapsack.

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description