class Solution {
/** Recursion */
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int ans = findMinCoins(coins, amount, n);
return -1;
return ans;
}
public int findMinCoins(int[] coins, int amount, int n)
{
// base condition: No coins left
// At this point, if amount > 0 (positive), we cannot form the remaining amount, because there are no coins left to use.
// Returning 0 here would mean 0 coins are needed, which is incorrect, because we cannot form the positive amount with no coins.
if(n == 0)
// 0 coins needed to make amount as 0
if(amount == 0)
return 0;
if(coins[n-1] <= amount)
{
// we can pick same coin multiple times
int pick = 1 + findMinCoins(coins, amount-coins[n-1], n);
int notPick = findMinCoins(coins, amount, n-1);
return Math.
min(pick, notPick
); }
return findMinCoins(coins, amount, n-1);
}
/** Memoization */
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int[][] t = new int[n+1][amount+1];
// when we have coins, but amount is always 0, so 0 coins needed to make amount as 0
for(int i=0; i<n+1; i++)
{
}
// when we do not have coins, but amount > 0
for(int j=0; j<n+1; j++)
{
}
int ans = findMinCoins(coins, amount, n, t);
return -1;
return ans;
}
public int findMinCoins(int[] coins, int amount, int n, int[][] t)
{
// base condition: No coins left
// At this point, if amount > 0 (positive), we cannot form the remaining amount, because there are no coins left to use.
// Returning 0 here would mean 0 coins are needed, which is incorrect, because we cannot form the positive amount with no coins.
if(n == 0)
// 0 coins needed to make amount as 0
if(amount == 0)
return 0;
if(t
[n
][amount
] != Integer.
MAX_VALUE - 1) return t[n][amount];
if(coins[n-1] <= amount)
{
// we can pick same coin multiple times
int pick = 1 + findMinCoins(coins, amount-coins[n-1], n, t);
int notPick = findMinCoins(coins, amount, n-1, t);
t
[n
][amount
] = Math.
min(pick, notPick
); return t[n][amount];
}
t[n][amount] = findMinCoins(coins, amount, n-1, t);
return t[n][amount];
}
/** Top-down approach */
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int[][] t = new int[n+1][amount+1];
for(int i=0; i<n+1; i++)
{
for(int j=0; j<amount+1; j++)
{
// when coins are 0, we cannot form the amount
if(i == 0)
// when amount to be formed is 0, then 0 coins needed
if(j == 0)
t[i][j] = 0;
}
}
for(int i=1; i<n+1; i++)
{
for(int j=0; j<amount+1; j++)
{
if(coins[i-1] <= j)
{
// we can pick same coin multiple times
int pick = 1 + t[i][j - coins[i-1]];
int notPick = t[i-1][j];
t
[i
][j
] = Math.
min(pick, notPick
); }
else
t[i][j] = t[i-1][j];
}
}
int ans = t[n][amount];
return -1;
return ans;
}
}