All Combinations That Sum to a Target With Repetition
Problem
Given an array of distinct positive candidates and a target, return every unique combination (multiset) where the chosen numbers sum to the target. Each candidate may be used unlimited times.
Sort candidates ascending. Recurse with the current start index and remaining target. At each step, iterate i = start..n-1: stop the loop when candidates[i] > remain (sorting makes this prune correct). Otherwise pick it, recurse with i (not i + 1) so it can be reused, then pop. Hit zero — emit the path.
Input
candidates = [2, 3, 6, 7], target = 7Output
[2,2,3] [7]2+2+3 = 7 (repeating 2). 7 alone. 6 alone leaves 1 — no valid completion.
def combination_sum(candidates, target):
candidates.sort()
out, path = [], []
def back(start, remain):
if remain == 0:
out.append(path.copy()); return
for i in range(start, len(candidates)):
if candidates[i] > remain: break
path.append(candidates[i])
back(i, remain - candidates[i])
path.pop()
back(0, target)
return out
function combinationSum(candidates, target) {
candidates.sort((a, b) => a - b);
const out = [], path = [];
function back(start, remain) {
if (remain === 0) { out.push(path.slice()); return; }
for (let i = start; i < candidates.length; i++) {
if (candidates[i] > remain) break;
path.push(candidates[i]);
back(i, remain - candidates[i]);
path.pop();
}
}
back(0, target);
return out;
}
List<List<Integer>> out = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
back(candidates, 0, target);
return out;
}
void back(int[] c, int start, int remain) {
if (remain == 0) { out.add(new ArrayList<>(path)); return; }
for (int i = start; i < c.length; i++) {
if (c[i] > remain) break;
path.add(c[i]);
back(c, i, remain - c[i]);
path.remove(path.size() - 1);
}
}
vector<vector<int>> out;
vector<int> path;
void back(vector<int>& c, int start, int remain) {
if (remain == 0) { out.push_back(path); return; }
for (int i = start; i < (int)c.size(); i++) {
if (c[i] > remain) break;
path.push_back(c[i]);
back(c, i, remain - c[i]);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& c, int target) {
sort(c.begin(), c.end());
back(c, 0, target);
return out;
}