function backtrack(nums: number[], target: number, start: number, path: number[], res: number[][]): void {
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 res: number[][] = [];
backtrack(nums, 5, 0, [], res);
console.log(res);The backtracking function finds all unique subsets of nums that sum to 5. The valid subsets are [1,4] and [2,3]. The subset [1,2,3] sums to 6, so it's invalid. The number 5 is not in the list, so [5] is invalid. The full list sums to 10, so [1,2,3,4] is invalid.
Greedy algorithms pick the best immediate option without considering future consequences. This can cause them to miss subsets that sum to the target because they don't explore all combinations.
function greedy(nums: number[], target: number): number[] {
const res: number[] = [];
let sum = 0;
for (const num of nums) {
if (sum + num <= target) {
res.push(num);
sum += num;
}
}
return res;
}
function backtrack(nums: number[], target: number, start: number, path: number[], res: number[][]): void {
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 = [2, 3, 5, 6];
const greedyResult = greedy(nums, 7);
const backtrackResult: number[][] = [];
backtrack(nums, 7, 0, [], backtrackResult);
console.log({greedyResult, backtrackResult});The greedy picks 2, then 3, then tries 5 but sum would be 10 > 7, so stops at [2,3]. Backtracking finds [2,5] as the only subset summing to 7. The option with [3,4] is invalid because 4 is not in the list.
function greedyCoinChange(coins: number[], amount: number): number[] {
coins.sort((a, b) => b - a);
const result: number[] = [];
for (const coin of coins) {
while (amount >= coin) {
result.push(coin);
amount -= coin;
}
}
if (amount !== 0) throw new Error('Cannot make exact change');
return result;
}
console.log(greedyCoinChange([1,3,4], 6));The greedy picks 4 first, then two 1s to make 6. It returns [4,1,1]. It does not throw error because amount reaches 0. It does not pick [3,3] because 4 is chosen first greedily.
The N-Queens problem requires checking all possible placements to avoid conflicts. Greedy algorithms make local choices that may block future queen placements, so backtracking is needed to explore and undo choices.