Memory-constrained coin changing for numbers up to one billion
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If the target amount can be as large as one billion, the textbook dynamic-programming table for coin change is the wrong tool. An array of size target + 1 is too large, and the usual O(target) memory cost becomes the real bottleneck long before runtime does.
The fix is to stop indexing states by every amount. For large targets, you usually need a method based on number theory, residue classes, or a greedy property of the denomination system.
Why Standard Dynamic Programming Fails
For the minimum-coin version of coin change, the classic recurrence is:
That works well when x is a few thousand or a few million. It does not scale to one billion because it needs memory proportional to the target.
A billion-element table is not a tuning problem. It is the wrong state model.
Before choosing a replacement, do two quick checks:
If target is not divisible by the gcd of the denominations, no exact solution exists.
Case 1: Canonical Coin Systems
Some denomination systems are canonical, which means a greedy algorithm already gives the minimum number of coins. Many real currency systems are designed this way.
In that case, the best memory-constrained algorithm is just greedy:
This uses constant extra memory and handles huge targets easily.
The catch is correctness. Greedy is not valid for arbitrary coin sets. For example, with coins [1, 3, 4], greedy makes 6 as 4 + 1 + 1, but the optimum is 3 + 3.
Case 2: Arbitrary Denominations with a Residue Graph
For arbitrary denominations, a useful bounded-memory technique is to work modulo the largest coin M instead of tracking every amount from 0 to target.
The idea is:
- keep only
Mstates, one per remainder moduloM - find the best way to reach each remainder
- once the correct remainder is reached, fill the rest with copies of the largest coin
To make this work for the minimum-coin problem, minimize the score M * coins_used - total_sum. That score stays unchanged when you add one more M coin, so it captures exactly the part of the solution that matters before the final fill step.
Here is a compact implementation:
This uses O(M) memory instead of O(target). That can be a dramatic reduction when target is huge and the largest denomination is moderate.
When This Strategy Is a Good Fit
The residue-graph method is useful when:
- coins are unbounded
- you need an exact answer
- target values are huge
- denomination magnitudes are much smaller than the target
It is not ideal if the largest denomination is itself enormous, because the state count becomes M. In that situation, you may need a problem-specific shortcut, a meet-in-the-middle strategy, or proof that the coin system is canonical and therefore greedy.
For production code, it is a good idea to validate the residue-based solver against a normal DP on small targets during testing. The large-target method is compact, but it is also more subtle than the standard recurrence.
Common Pitfalls
The biggest mistake is assuming that greedy always works. It only works for specific coin systems, not for arbitrary denomination sets.
Another mistake is trying to compress the normal DP table slightly and hoping that will make one-billion targets practical. If the algorithm still depends on every amount from 0 to target, the memory problem has not actually been solved.
People also forget the gcd reachability test. That check is cheap and can reject impossible targets immediately.
Finally, residue-based methods depend heavily on choosing the right modulus and objective. Using the largest denomination and minimizing the adjusted score is what keeps the state space small while still targeting the minimum number of coins.
Summary
- A full DP table is not practical when the target can reach one billion.
- Start with a
gcdcheck to rule out impossible targets. - Use greedy only when the denomination system is known to be canonical.
- For arbitrary unbounded coins, a residue-graph method can reduce memory from
O(target)toO(max_coin). - Large-target solvers should be cross-checked against ordinary DP on small test cases.
- The right state representation matters more than micro-optimizing the classic algorithm.

