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];
}
}