◀ THE GRIND — 2-D DYNAMIC PROGRAMMING

Coin Change II

MEDIUM✓ CHIP-TIMEDLC #518 — FULL STATEMENT ↗

The drill: Given coin denominations and a target amount, count how many different combinations of coins add up to it exactly — order doesn't matter, and each denomination can be reused any number of times.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A set of coin denominations and a target amount arrive together, and the task is to count how many different combinations of those coins add up to the target exactly.

Each denomination can be used any number of times, and order doesn't matter for counting — using a 1-coin then a 2-coin is the same combination as a 2-coin then a 1-coin, so it's only counted once, not twice.

The output is that combination count, which is zero when no combination of the given coins can reach the target exactly.

EX 01
amount = 0 · coins = [4]
1
ZERO AMOUNT, THE EMPTY COMBINATION COUNTS
EX 02
amount = 6 · coins = [3]
1
SINGLE DENOMINATION, EXACT MULTIPLE
EX 03
amount = 5 · coins = [3]
0
SINGLE DENOMINATION, NOT A MULTIPLE
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Two combinations that use the same coins in a different order aren't different combinations. Processing coins one whole denomination at a time — instead of one choice at a time — is what keeps order from being double counted.

HINT 2 THE STRUCTURE

With a fixed set of coins considered so far, the ways to make amount a either skip the newest coin entirely, or use at least one of it — using one just needs the ways to make a minus that coin's value, with the same coin still allowed again.

HINT 3 ONE STEP FROM THE ANSWER

DP over amount: ways[0] = 1. For each coin in turn, sweep amounts upward from that coin's value and do ways[a] += ways[a − coin]. Finishing one coin's whole sweep before starting the next is what prevents order from mattering.

COACH'S BOARD — THE PATTERN, STEP BY STEP
COINS, ONE DENOMINATION AT A TIMEPATTERN · UNBOUNDED KNAPSACK — COMBINATIONSamount = 5 · coins = [1, 2]
1
0
0
0
0
0
STEP 1

amount=5, coins=[1,2]. ways[0]=1 — the empty combination reaches zero; everything else is unknown so far.

STEP 1 / 7 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/coin-change-ii.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        dp = [0] * (amount + 1)
        dp[0] = 1
        for coin in coins:
            for a in range(coin, amount + 1):
                dp[a] += dp[a - coin]
        return dp[amount]
TIME O(AMOUNT · COINS)SPACE O(AMOUNT)PYTHON · RACE PACE · 8 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED