Coin Change II
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ coins.length ≤ 15 - ◆
1 ≤ coins[i] ≤ 100 - ◆
0 ≤ amount ≤ 1000
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteTo avoid counting the same combination twice (using a 2 then a 3 is the same combination as a 3 then a 2), process the coin denominations in a fixed order and, at each one, decide how many times to use it before moving permanently on to the next denomination. From a given coin and remaining amount, there are two options: use this same coin again (if it still fits, lowering the remaining amount by its value) or move on to the next coin denomination entirely (leaving the remaining amount untouched). Reaching a remaining amount of exactly 0 counts as one valid combination; running out of coin denominations before that contributes nothing. Adding up the ways found by both options at every step counts every combination exactly once.
O(2^amount)O(coins.length + amount)1class Solution {
2 private int[] coins;
3
4 public int coinChangeII(int[] coins, int amount) {
5 this.coins = coins;
6 return solve(0, amount);
7 }
8
9 private int solve(int i, int remaining) {
10 if (remaining == 0) return 1;
11 if (i == coins.length) return 0;
12 int count = 0;
13 if (coins[i] <= remaining) count += solve(i, remaining - coins[i]);
14 count += solve(i + 1, remaining);
15 return count;
16 }
17}Optimal — Bottom-Up 1D DP
OptimalTrack, for every amount from 0 up to the target, how many combinations of coins make it exactly — starting from exactly one way to make amount 0 (use no coins). Processing one coin denomination completely before moving to the next, and sweeping that coin's update forward from its own value up to the target, lets that coin be reused any number of times within its own pass while still counting each combination of denominations only once overall (since a combination is defined by how many of each coin it uses, not the order they're added in). After every coin denomination has been swept through, the entry at the target amount holds the total combination count.
O(coins.length × amount)O(amount)1class Solution {
2 public int coinChangeII(int[] coins, int amount) {
3 int[] dp = new int[amount + 1];
4 dp[0] = 1;
5 for (int c : coins) {
6 for (int a = c; a <= amount; a++) {
7 dp[a] += dp[a - c];
8 }
9 }
10 return dp[amount];
11 }
12}