function backtrack(nums, target, start, path, res) {
if (target === 0) {
res.push([...path]);
return;
}
for (let i = start; i < nums.length; i++) {
if (nums[i] > target) continue;
path.push(nums[i]);
backtrack(nums, target - nums[i], i + 1, path, res);
path.pop();
}
}
const nums = [1, 2, 3, 4];
const target = 5;
const result = [];
backtrack(nums, target, 0, [], result);
console.log(result);The backtracking function finds all unique subsets that sum to 5. The subsets [1,4] and [2,3] sum to 5. The subset [1,2,3] sums to 6, so it is excluded. There is no single element 5 in the array, so [5] is invalid. The full array sums to 10, so [1,2,3,4] is invalid.
Greedy algorithms pick the best option at each step without considering future consequences. For subset sum, this can miss combinations that add up correctly because it doesn't explore all possibilities.
function greedyChange(coins, amount) {
coins.sort((a,b) => b - a);
let count = 0;
for (let coin of coins) {
while (amount >= coin) {
amount -= coin;
count++;
}
}
return count;
}
console.log(greedyChange([1,3,4], 6));The code sorts coins descending to [4,3,1]. For amount=6: picks 4 once (amount=2, count=1), skips 3 (2 < 3), picks 1 twice (amount=0, count=3). Returns 3.
Minimum coins needed is 2 (3+3). Greedy returns suboptimal solution of 3 coins.
function backtrack(nums, target, start, path, res) {
if (target === 0) {
res.push([...path]);
return;
}
for (let i = start; i < nums.length; i++) {
if (nums[i] > target) continue;
path.push(nums[i]);
backtrack(nums, target - nums[i], i + 1, path, res);
path.pop();
}
}
function greedy(nums, target) {
nums.sort((a,b) => b - a);
let res = [];
for (let coin of nums) {
if (coin <= target) {
res.push(coin);
target -= coin;
}
}
return res;
}
const nums = [2,4,6,8];
const target = 8;
const backRes = [];
backtrack(nums, target, 0, [], backRes);
const greedyRes = greedy(nums, target);
console.log({backRes, greedyRes});Backtracking finds subsets [2,6] and [8] that sum to 8. Greedy picks the largest coin 8 first, so greedyRes is [8].
Backtracking tries all possible combinations, so it guarantees finding a solution if one exists. Greedy makes local choices that may miss the correct combination.
