322 - Coin Chainge

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:

Input: coins = [1, 2, 5], amount = 11
Output: 3 
Explanation: 11 = 5 + 5 + 1

Example 2:

Input: coins = [2], amount = 3
Output: -1

Note: You may assume that you have an infinite number of each kind of coin.

Recursive

class Solution {
    public int coinChange(int[] coins, int amount) {
        // index: amount
        // cell: least number of coins required to obtain the amount
        Integer[] memo = new Integer[amount + 1];
        return coinChange(coins, amount, memo);
    }

    private int coinChange(int[] coins, int amount, final Integer[] memo) {
        // 0 coins required for 0 amount
        if (amount == 0) {
            return 0;
        }

        if (amount < 0) {
            return -1;
        }

        if (memo[amount] != null) {
            return memo[amount];
        }

        Integer minCoins = null;

        for (final int coin : coins) {
            if (amount - coin >= 0) {
                if (memo[amount - coin] == null) {
                    memo[amount - coin] = coinChange(coins, amount - coin, memo);
                }

                if (memo[amount - coin] != null && memo[amount - coin] != -1) {
                    if (minCoins == null) {
                        minCoins = memo[amount - coin];
                    } else {
                        minCoins = Math.min(minCoins, memo[amount - coin]);
                    }
                }
            }
        }

        if (minCoins == null) {
            // no coin combo available to get this amount
            memo[amount] = -1;
        } else {
            memo[amount] = 1 + minCoins;
        }

        return memo[amount];
    }
}

Iterative

class Solution {
    public int coinChange(int[] coins, int amount) {
        
        // index: amount
        // cell: least number of coins required to obtain the amount
        final int[] memo = new int[amount + 1];
        Arrays.fill(memo, -1);

        // 0 coins required for 0 amount
        memo[0] = 0;

        if (amount < 0) {
            return -1;
        }

        for (int i = 1; i <= amount; i++) {
            
            int minCoins = Integer.MAX_VALUE;
            for (final int coin : coins) {
                // -1 represents that no coin combo can be equal to the amount
                if (i - coin >= 0 && memo[i - coin] != -1) {
                    minCoins = minCoins < memo[i - coin] ? minCoins : memo[i - coin];
                }    
            }    

            if (minCoins != Integer.MAX_VALUE) {
                memo[i] = 1 + minCoins;
            }
        }
        return memo[amount];
    }
}