diff --git a/Dynamic-Programming/CoinChange.js b/Dynamic-Programming/CoinChange.js index c7050177b..35825d7fb 100644 --- a/Dynamic-Programming/CoinChange.js +++ b/Dynamic-Programming/CoinChange.js @@ -1,45 +1,33 @@ -function change (coins, amount) { +/** + * @params {Array} coins + * @params {Number} amount + */ +export const change = (coins, amount) => { + // Create and initialize the storage const combinations = new Array(amount + 1).fill(0) combinations[0] = 1 - + // Determine the direction of smallest sub-problem for (let i = 0; i < coins.length; i++) { - const coin = coins[i] - - for (let j = coin; j < amount + 1; j++) { - combinations[j] += combinations[j - coin] + // Travel and fill the combinations array + for (let j = coins[i]; j < combinations.length; j++) { + combinations[j] += combinations[j - coins[i]] } } return combinations[amount] } - -function minimumCoins (coins, amount) { - // minimumCoins[i] will store the minimum coins needed for amount i - const minimumCoins = new Array(amount + 1).fill(0) - - minimumCoins[0] = 0 - - for (let i = 1; i < amount + 1; i++) { - minimumCoins[i] = Number.MAX_SAFE_INTEGER - } - for (let i = 1; i < amount + 1; i++) { - for (let j = 0; j < coins.length; j++) { - const coin = coins[j] - if (coin <= i) { - const subRes = minimumCoins[i - coin] - if (subRes !== Number.MAX_SAFE_INTEGER && subRes + 1 < minimumCoins[i]) { - minimumCoins[i] = subRes + 1 - } - } +/** + * @params {Array} coins + * @params {Number} amount + */ +export const coinChangeMin = (coins, amount) => { + const map = { 0: 1 } + for (let i = 1; i <= amount; i++) { + let min = Infinity + for (const coin of coins) { + if (i < coin) continue + min = Math.min(min, 1 + map[i - coin]) } + map[i] = min } - return minimumCoins[amount] + return map[amount] === Infinity ? -1 : map[amount] - 1 } - -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)) -} - -main() diff --git a/Dynamic-Programming/tests/CoinChange.test.js b/Dynamic-Programming/tests/CoinChange.test.js new file mode 100644 index 000000000..6df3c66a3 --- /dev/null +++ b/Dynamic-Programming/tests/CoinChange.test.js @@ -0,0 +1,44 @@ +import { change, coinChangeMin } from '../CoinChange' + +test('Base Case 1', () => { + const coins = [2, 3, 5] + const amount = 0 + expect(change(coins, amount)).toBe(1) + expect(coinChangeMin(coins, amount)).toBe(0) +}) +test('Base Case 2', () => { + const coins = [] + const amount = 100 + expect(change(coins, amount)).toBe(0) + expect(coinChangeMin(coins, amount)).toBe(-1) +}) +test('Test Case 1', () => { + const coins = [2, 4, 5] + const amount = 12 + expect(change(coins, amount)).toBe(5) + expect(coinChangeMin(coins, amount)).toBe(3) +}) +test('Test Case 2', () => { + const coins = [5, 2, 3, 7, 6, 1, 12, 11, 9, 15] + const amount = 45 + expect(change(coins, amount)).toBe(12372) + expect(coinChangeMin(coins, amount)).toBe(3) +}) +test('Test Case 3', () => { + const coins = [2] + const amount = 3 + expect(change(coins, amount)).toBe(0) + expect(coinChangeMin(coins, amount)).toBe(-1) +}) +test('Test Case 4', () => { + const coins = [3, 5, 7, 8, 9, 10, 11] + const amount = 500 + expect(change(coins, amount)).toBe(35502874) + expect(coinChangeMin(coins, amount)).toBe(46) +}) +test('Test Case 5', () => { + const coins = [10] + const amount = 10 + expect(change(coins, amount)).toBe(1) + expect(coinChangeMin(coins, amount)).toBe(1) +})