-
-
Notifications
You must be signed in to change notification settings - Fork 223
Expand file tree
/
Copy pathcoinsChange.js
More file actions
80 lines (74 loc) · 2.13 KB
/
coinsChange.js
File metadata and controls
80 lines (74 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* Returns the minimum number of coins needed to make up the given amount.
* Uses bottom-up dynamic programming.
* @param {number[]} coins - Array of coin denominations (positive integers)
* @param {number} amount - Target amount (non-negative integer)
* @returns {number} Minimum number of coins, or -1 if not possible
*/
function coinChangeDP(coins, amount) {
const dp = new Array(amount + 1).fill(amount + 1);
dp[0] = 0;
for (let i = 1; i <= amount; i++) {
for (const coin of coins) {
if (i - coin >= 0) {
dp[i] = Math.min(dp[i], 1 + dp[i - coin]);
}
}
}
return dp[amount] === amount + 1 ? -1 : dp[amount];
}
/**
* Returns the minimum number of coins needed to make up the given amount.
* Uses recursion with memoization.
* @param {number[]} coins
* @param {number} amount
* @returns {number}
*/
function coinChangeRecursive(coins, amount) {
const memo = {};
function helper(rem) {
if (rem === 0) return 0;
if (rem < 0) return Infinity;
if (memo[rem] !== undefined) return memo[rem];
let min = Infinity;
for (const coin of coins) {
min = Math.min(min, 1 + helper(rem - coin));
}
memo[rem] = min;
return min;
}
const res = helper(amount);
return res === Infinity ? -1 : res;
}
// Test cases
const testCases = [
{ coins: [1, 3, 4, 5], amount: 7, expected: 2 },
{ coins: [2, 4], amount: 3, expected: -1 },
{ coins: [1], amount: 0, expected: 0 },
{ coins: [2], amount: 1, expected: -1 },
{ coins: [1, 2, 5], amount: 11, expected: 3 },
{ coins: [], amount: 5, expected: -1 },
{ coins: [2, 5, 10, 1], amount: 27, expected: 4 },
];
for (const { coins, amount, expected } of testCases) {
console.log(
`coins = [${coins}], amount = ${amount} | DP: ${coinChangeDP(
coins,
amount
)} | Recursive: ${coinChangeRecursive(
coins,
amount
)} | Expected: ${expected}`
);
}
// Edge case: invalid input
try {
coinChangeDP([1, -2], 5);
} catch (e) {
console.log("Error (as expected for invalid coins):", e.message);
}
try {
coinChangeDP([1, 2], -5);
} catch (e) {
console.log("Error (as expected for negative amount):", e.message);
}