Combination Sum Solution
Given an array of distinct integers and a target, find all unique combinations where the chosen numbers sum to the target. Each number may be used unlimited times.
Problem Statement
Given an array of distinct integers candidates and a target integer target, return all unique combinations of candidates that sum to target. The same number may be chosen an unlimited number of times. Two combinations are unique if the frequency of at least one number differs.
Brute Force โ Try All Multi-sets
Generate all non-decreasing sequences of candidates up to length target/min(candidates) and check if each sums to target. This is equivalent to an unconstrained DFS that does not prune when the running sum already exceeds the target.
Any combination summing to target will be found by exhaustive enumeration. Since candidates can repeat, the space is all multi-sets over the candidate array bounded by the target.
target. Pruning the branch the moment remaining < 0 eliminates entire subtrees. Additionally, starting the inner loop from the current index (not 0) prevents generating duplicates like [3,2] when [2,3] has already been explored.
| Metric | Value |
|---|---|
| Time | O(2^(t/m)) where t = target, m = min candidate โ exponential |
| Space | O(t/m) โ max recursion depth |
Backtracking with Pruning โ O(2^(t/m))
Sort the candidates so that once a candidate exceeds the remaining target, no further candidate can work. This prunes entire branches early. Starting the loop from i (not 0) prevents duplicate orderings.
- Sort candidates to enable early termination.
- State:
startindex (no element beforestartis reconsidered) andremainingsum. - Base case success:
remaining == 0โ add copy of path to result. - Pruning: if
candidates[i] > remaining, break โ all subsequent candidates are larger (sorted). - Reuse: recurse with
i(noti+1) to allow reusing the current candidate.
- Any "find all combinations that sum to X" problem.
- The signals are: output is a list of lists, elements can be reused or have a limited use count, and duplicates must be avoided.
- This is the base for LC 40 (Combination Sum II, no reuse + duplicates), LC 216 (Combination Sum III, fixed size k), and LC 377 (Combination Sum IV, count only).
start = i and not start = 0: - Starting from
imeans the next call can still pick the same candidate (allowing repeats), but can never pick an earlier candidate (preventing duplicates like [3,2] = [2,3]). - This single invariant eliminates all ordering duplicates without needing a de-duplication set.
Visual Walkthrough
Trace for candidates = [2, 3, 6, 7], target = 7. Only branches that reach rem=0 produce results.
Code โ Java & Python
Complexity Analysis
| Approach | Time | Space | Trade-off |
|---|---|---|---|
| Brute force (no pruning) | O(n^(t/m)) | O(t/m) | Many redundant paths, duplicate orderings |
| DP (count only) | O(n ยท t) | O(t) | Can count combinations but cannot enumerate them |
| Backtracking + pruning โ optimal | O(2^(t/m)) | O(t/m) | Enumerates all solutions, prunes invalid branches immediately |
- DP works when you only need to count combinations or find the minimum number.
- Here the output is the actual combinations themselves โ you must enumerate them.
- DP cannot recover the full list without reconstruction overhead equivalent to backtracking.
Edge Cases & Pitfalls
| Case | Input | Why It Matters |
|---|---|---|
| Single candidate equals target | [7], target=7 | Result: [[7]]. One element, base case fires immediately. |
| No valid combination | [3,5], target=4 | Result: []. All paths are pruned before reaching 0. |
| Minimum candidate = 2 | [2], target=1 | 2 > 1, pruned at first iteration. Returns []. |
| Target exactly divisible | [2], target=8 | Only one path: [2,2,2,2]. Depth = target/min = 4. |
| Multiple paths possible | [2,3,6,7], target=7 | Both [2,2,3] and [7] valid. Algorithm finds both. |
| Large candidate exceeds target | [2,100], target=6 | 100 > 6 is pruned immediately after sort. No wasted recursion. |
backtrack(i + 1, ...) instead of backtrack(i, ...). Using i+1 means each candidate can only be used once, giving you LC 40 (Combination Sum II) behavior, not LC 39. The problem explicitly says "may be used unlimited times" โ you must pass i to allow the same index to be chosen again on the next level.