Coin Change (min coins) and Coin Change 2 (number of ways). — Cracked Java
// Data Structures & Algorithms · Dynamic Programming
MidCodingAmazon

Coin Change (min coins) and Coin Change 2 (number of ways).

Problem (min coins). Given coin denominations and an amount, return the fewest coins that sum to it, or -1 if impossible. Coins are unlimited.

Problem (count ways). Coin Change 2 — return the number of distinct combinations that sum to amount.

Both are unbounded knapsack: each coin reusable, capacity = amount. The subtle difference is in the loop order.

Coin Change — minimum coins

State dp[a] = fewest coins to make amount a. Try every coin as the last one used:

dp[a] = min over coins c (c <= a) of (dp[a - c] + 1)
int coinChange(int[] coins, int amount) {
    int[] dp = new int[amount + 1];
    Arrays.fill(dp, amount + 1);          // sentinel "infinity" — amount+1 is unreachable
    dp[0] = 0;
    for (int a = 1; a <= amount; a++)
        for (int c : coins)
            if (c <= a)
                dp[a] = Math.min(dp[a], dp[a - c] + 1);
    return dp[amount] > amount ? -1 : dp[amount];
}

O(amount · coins) time, O(amount) space. amount + 1 is a safe sentinel since no valid answer exceeds amount.

Coin Change 2 — count combinations

Here order must not matter (1+2 and 2+1 are the same combination). The trick is to put the coin loop outside the amount loop, so each coin is fully processed before the next — this counts each combination exactly once.

int change(int amount, int[] coins) {
    int[] dp = new int[amount + 1];
    dp[0] = 1;                            // one way to make 0: take nothing
    for (int c : coins)                   // coin loop OUTSIDE
        for (int a = c; a <= amount; a++)
            dp[a] += dp[a - c];
    return dp[amount];
}

If you swapped the loops (amount outside, coin inside), you would count permutations instead — that answers a different question (number of ordered sequences).

Mark your status