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 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