function combinationSum(cands, target) {const res = [], path = [];
function backtrack(start, remain) { if (remain === 0) { res.push([...path]); return; }if (remain < 0) return;
for (let i = start; i < cands.length; i++) {path.push(cands[i]);
backtrack(i, remain - cands[i]); // reuse i
path.pop(); // undo
}
}
backtrack(0, target);◄
return res;
}
Instead of tracking the running sum, track what is LEFT (remain). Choosing a number simply subtracts it from remain — and remain = 0 means success.
Two base cases fall out naturally: remain == 0 → record the path; remain < 0 → you overshot, so prune this branch immediately.
Because a number can be reused, recurse with i (not i + 1) — the same candidate stays available at the next level.
Passing start = i (never going backwards) is what prevents duplicates like [2,3] and [3,2] from both appearing.