diff --git a/Dynamic-Programming/CoinChange.js b/Dynamic-Programming/CoinChange.js index c7050177b..996ed8ecc 100644 --- a/Dynamic-Programming/CoinChange.js +++ b/Dynamic-Programming/CoinChange.js @@ -1,4 +1,4 @@ -function change (coins, amount) { +function change(coins, amount) { const combinations = new Array(amount + 1).fill(0) combinations[0] = 1 @@ -12,7 +12,47 @@ function change (coins, amount) { return combinations[amount] } -function minimumCoins (coins, amount) { +/** Coin-change combination using recursive approach along with Memoization + * @param {number} amount + * @param {number[]} coins + */ +const changeRecursive = (amount, coins) => { + const mem = new Map() + return coinChangeComb(amount, coins, 0, mem) +} +/** Coin-change combination using recursive approach along with Memoization + * @param {number} amount + * @param {number[]} coins + * @param {number} idx + * @param {Map} mem + */ + +const coinChangeComb = (amount, coins, idx, mem) => { + // Negative Base Case + if (amount < 0 || idx === coins.length) { + return 0 + } + // Positive Base Case + if (amount === 0) { + return 1 + } + + // Main Case + // Check if the recursive function call results is already memoized + if (mem.has(`${amount} - ${idx}`)) { + return mem.get(`${amount} - ${idx}`) + } + let res = 0 + // Consider the coin at index idx + res += coinChangeComb(amount - coins[idx], coins, idx, mem) + // Leave the coin at index idx + res += coinChangeComb(amount, coins, idx + 1, mem) + // Cache the intermediate result in mem + mem.set(`${amount} - ${idx}`, res) + return res +} + +function minimumCoins(coins, amount) { // minimumCoins[i] will store the minimum coins needed for amount i const minimumCoins = new Array(amount + 1).fill(0) @@ -26,7 +66,10 @@ function minimumCoins (coins, amount) { const coin = coins[j] if (coin <= i) { const subRes = minimumCoins[i - coin] - if (subRes !== Number.MAX_SAFE_INTEGER && subRes + 1 < minimumCoins[i]) { + if ( + subRes !== Number.MAX_SAFE_INTEGER && + subRes + 1 < minimumCoins[i] + ) { minimumCoins[i] = subRes + 1 } } @@ -35,11 +78,27 @@ function minimumCoins (coins, amount) { return minimumCoins[amount] } -function main () { +function main() { const amount = 12 const coins = [2, 4, 5] - console.log('Number of combinations of getting change for ' + amount + ' is: ' + change(coins, amount)) - console.log('Minimum number of coins required for amount :' + amount + ' is: ' + minimumCoins(coins, amount)) + console.log( + 'Number of combinations of getting change for ' + + amount + + ' is: ' + + change(coins, amount) + ) + console.log( + 'Number of combinations of getting change for ' + + amount + + ' is: ' + + changeRecursive(coins, amount) + ) + console.log( + 'Minimum number of coins required for amount :' + + amount + + ' is: ' + + minimumCoins(coins, amount) + ) } main()