Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.
The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]
Explanation:
2 + 2 + 3 = 7
7 = 7
Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]
Input: candidates = [2], target = 1
Output: []
We need combinations (not permutations), so [2,2,3] and [2,3,2] are the same.
Key difference from Subsets: We can reuse elements, and we have a target sum constraint.
Approach: Use backtracking with:
This is a Backtracking with Target problem:
def backtrack(start, current, total):
if total == target:
result.append(current.copy())
return
if total > target: # Pruning
return
for i in range(start, len(candidates)):
current.append(candidates[i])
# Can reuse same element: pass i (not i+1)
backtrack(i, current, total + candidates[i])
current.pop()
Key points:
i (not i+1) to allow reusestart index to avoid duplicatesSort candidates first for better pruning:
candidates[i] + total > target, all larger elements will also exceedTime: O(n^(t/m)) where:
Space: O(t/m) recursion depth
1import java.util.*;
2
3class Solution {
4 public List<List<Integer>> combinationSum(int[] candidates, int target) {
5 List<List<Integer>> result = new ArrayList<>();
6 backtrack(0, candidates, target, new ArrayList<>(), 0, result);
7 return result;
8 }
9
10 private void backtrack(int start, int[] candidates, int target,
11 List<Integer> current, int total,
12 List<List<Integer>> result) {
13 // Found valid combination
14 if (total == target) {
15 result.add(new ArrayList<>(current));
16 return;
17 }
18
19 // Prune: exceeded target
20 if (total > target) {
21 return;
22 }
23
24 // Try each candidate starting from 'start'
25 for (int i = start; i < candidates.length; i++) {
26 current.add(candidates[i]);
27 // Can reuse same element: pass i (not i+1)
28 backtrack(i, candidates, target, current, total + candidates[i], result);
29 current.remove(current.size() - 1);
30 }
31 }
32}
33