01
Problem Statement
Given an array of distinct positive integers candidates and a positive integer target, return all unique combinations of numbers from candidates where the chosen numbers sum to target. The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one chosen number is different.
- We need to list all such combinations (not just the count). Backtracking (DFS) is the natural approach: at each step, choose a candidate and recurse with the remaining target, or skip to the next candidate.
- To avoid duplicate combinations (e.g. [2,2,3] vs [2,3,2]), we iterate candidates in order and only consider candidates from the current index onward when we "take" a number.
02
Key Observations
- Backtracking: We maintain a
path(current combination) andremaining(target minus sum of path). From indexi, we can either (1) takecandidates[i](add to path, reduce remaining, stay atito allow reuse) or (2) skipcandidates[i](move toi+1). Whenremaining == 0, we have a valid combination — add a copy ofpathto the result. Whenremaining < 0or we have exhausted candidates, backtrack. - Sorting
candidatesis optional but can help prune (stop whencandidates[i] > remaining). - For counting combinations only, we could use DP:
dp[t] = number of ways to make sum t;dp[t] += dp[t - c]for eachcin candidates.
03
Approach
High-level: DFS/backtrack: at each call we have a start index and remaining target. Try adding candidates[i] for i >= start (so we can reuse), recurse with same i and remaining - candidates[i]; when remaining == 0, record the path. Then backtrack (remove from path) and try next index.
Steps:
- Optionally sort
candidates. Calldfs(candidates, target, 0, path, result). - In
dfs(remaining, start): ifremaining == 0, add copy ofpathtoresultand return. Ifremaining < 0orstart >= n, return. Fori = start..n-1: ifcandidates[i] > remainingbreak (if sorted).path.add(candidates[i]),dfs(remaining - candidates[i], i),path.remove. - Return
result.
04
Implementation
Java
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(candidates);
dfs(candidates, target, 0, new ArrayList<>(), result);
return result;
}
void dfs(int[] c, int t, int start, List<Integer> path, List<List<Integer>> result) {
if (t == 0) { result.add(new ArrayList<>(path)); return; }
if (t < 0) {
return;
}
for (int i = start; i < c.length; i++) {
path.add(c[i]);
dfs(c, t - c[i], i, path, result);
path.remove(path.size() - 1);
}
}05
Test Cases
Example 1
Input
candidates = [2,3,6,7], target = 7
Expected
[[2,2,3],[7]]Explanation
2+2+3=7 and 7=7.
06
Complexity Analysis
- Time: O(2^target) in worst case.
- Space: O(target) for recursion.
07
Follow-ups
- Combination Sum II: each candidate used at most once; avoid duplicate combinations.