Skip to content
Forge Learn/1D Dynamic Programming

Coin Change & 1D DP Patterns

6 min read

You'll learn to

  • -Implement coin_change(coins, amount) using a bottom-up dp array
  • -Explain what dp[i] represents and why it is initialized to infinity
  • -Apply the general 1D DP recipe (define dp[i], find the recurrence, pick the base case) to a new problem

Coin change asks a slightly harder question than climbing stairs: given a list of coin denominations and a target amount, what is the fewest coins needed to make exactly that amount (or -1 if it cannot be made at all)? Unlike climbing stairs, each step of the recurrence has to consider several possible "previous" amounts - one for every coin denomination - rather than a fixed one or two.

Defining dp[i]

Let dp[i] be the minimum number of coins needed to make amount i. For every amount i from 1 up to the target, and for every coin denomination that is small enough to subtract from i, dp[i] can potentially be built from dp[i - coin] plus one more coin. Taking the minimum over every valid coin gives the best answer for that amount - and once every smaller amount has been solved, i itself can be solved by reusing those answers instead of recursing.

coin_change(coins, amount) - dp[i] = min coins to make amount i

dp is initialized to infinity everywhere except dp[0], which means "not yet known to be reachable." As the loop runs, any amount that actually can be made from some combination of coins gets a finite value written in via the `min`-style comparison, and infinity values simply never win that comparison. If dp[amount] is still infinity once the loop finishes, no combination of coins can make that exact amount, so the function returns -1.

The General 1D DP Recipe

Coin change and climbing stairs look different on the surface, but both were solved with the same three-step recipe - one worth applying to any new 1D DP problem you encounter:

  • -Define what dp[i] means in plain language, in terms of the smallest unit of progress the problem has (a step count, an amount, a prefix length).
  • -Find the recurrence - how dp[i] can be built from one or more strictly smaller dp[j] values that are already known.
  • -Pick the base case(s) - the smallest i where the answer is obvious without needing the recurrence (dp[0] = 0 coins, or n <= 2 steps).
  • -Choose the iteration order that guarantees every dp[j] the recurrence depends on is already filled in before dp[i] needs it - almost always smallest-to-largest for these forward-looking dependencies.

A dp array full of "impossible" sentinel values (infinity, or -1, depending on convention) is a normal and expected part of many DP problems - the bug to watch for is comparing against that sentinel incorrectly, e.g. forgetting the coin <= i bounds check and indexing dp with a negative number.

Check Yourself1 / 3

In coin_change, what does dp[i] represent?

Ready to Build This?

Level 70: 1D Dynamic Programming asks you to implement climb_stairs(n) and coin_change(coins, amount) using exactly the bottom-up tabulation approach from these two chapters.

ScaleDojo Logo
Initializing ScaleDojo