Coin Change Problem
Finds the minimum number of coins from a given set of denominations that sum to a target amount, using bottom-up dynamic programming (unbounded knapsack variant).
Syntax
coinChange(coins, amount) Parameters
| Name | Type | Required | Description |
|---|---|---|---|
coins | number[] | Yes | Array of distinct coin denominations (positive integers). |
amount | number | Yes | Target sum to achieve. Non-negative integer. |
Returns
number — Minimum number of coins, or -1 if the amount cannot be formed.
Examples
function coinChange(coins, amount) {
const dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0;
for (let a = 1; a <= amount; a++) {
for (const coin of coins) {
if (coin <= a) dp[a] = Math.min(dp[a], dp[a - coin] + 1);
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
}
console.log(coinChange([1, 5, 6, 9], 11));
console.log(coinChange([2], 3));
Output
2
-1
// Count the number of ways to make the amount (coin change II)
function coinChangeWays(coins, amount) {
const dp = new Array(amount + 1).fill(0);
dp[0] = 1;
for (const coin of coins) {
for (let a = coin; a <= amount; a++) {
dp[a] += dp[a - coin];
}
}
return dp[amount];
}
console.log(coinChangeWays([1, 2, 5], 5));
Output
4
Notes
| Case | Time | Space |
|---------|-----------|-------|
| Best | O(n·W) | O(W) |
| Average | O(n·W) | O(W) |
| Worst | O(n·W) | O(W) |
where n = number of coin types and W = amount. The DP builds up from
dp[0] = 0. Coins can be reused (unbounded), so inner loop goes left-to-
right. Coin Change II (counting ways) iterates coins in the outer loop
to avoid counting the same combination multiple times (order-insensitive).
The greedy algorithm (always take the largest coin ≤ remaining) does NOT
always give the optimal solution (e.g. coins [1,5,6,9], amount 11 —
greedy gives 9+1+1=3 coins, DP gives 6+5=2 coins).