class Solution {
// idea: Do not add +1 when picking a coin. Each valid combination is counted exactly once.
/** Recursion */
public int change(int amount, int[] coins) {
int n = coins.length;
return findWays(coins, amount, n);
}
public int findWays(int[] coins, int amount, int n)
{
// base condition: when amount becomes 0 then we found valid combination
if(amount == 0)
return 1;
// 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)
return 0;
if(coins[n-1] <= amount)
{
int pick = findWays(coins, amount-coins[n-1], n);
int notPick = findWays(coins, amount, n-1);
return pick + notPick;
}
return findWays(coins, amount, n-1);
}
/** Memoization */
public int change(int amount, int[] coins) {
int n = coins.length;
// create a matrix
int[][] t = new int[n+1][amount+1];
// initialise the matrix
for(int i=0; i<n+1; i++)
for(int j=0; j<n+1; j++)
return findWays(coins, amount, n, t);
}
public int findWays(int[] coins, int amount, int n, int[][] t)
{
// base condition: when amount becomes 0 then we found valid combination
if(amount == 0)
return 1;
// 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)
return 0;
if(t[n][amount] != 0)
return t[n][amount];
if(coins[n-1] <= amount)
{
int pick = findWays(coins, amount-coins[n-1], n, t);
int notPick = findWays(coins, amount, n-1, t);
t[n][amount] = pick + notPick;
return t[n][amount];
}
t[n][amount] = findWays(coins, amount, n-1, t);
return t[n][amount];
}
/** Top-down */
public int change(int amount, int[] coins) {
int n = coins.length;
// create a matrix
int[][] t = new int[n+1][amount+1];
// initialise the matrix with base condition
for(int i=0; i<n+1; i++)
{
for(int j=0; j<amount+1; j++)
{
// when we reach end of the array
if(i == 0)
t[i][j] = 0;
// when sum is always 0, then empty subset
if(j == 0)
t[i][j] = 1;
}
}
for(int i=1; i<n+1; i++)
{
for(int j=1; j<amount+1; j++)
{
if(coins[i-1] <= j)
{
int pick = t[i][j - coins[i-1]];
int notPick = t[i-1][j];
t[i][j] = pick + notPick;
}
else
t[i][j] = t[i-1][j];
}
}
return t[n][amount];
}
}