Combination Sum II

Medium Recursion & Backtracking Pick / Not-Pick Original on LeetCode

Combination Sum II is a medium recursion & backtracking problem solved with the pick / not-pick pattern. The best approach, optimal (sort, skip equal siblings, break early), runs in O(n · 2ⁿ) time and O(n) space. Below are 2 approaches in Java, from generate and deduplicate up.

Problem

Given candidates (which may contain duplicates) and a target, return all unique combinations that sum to target. Each element can be used at most once, and the answer must not contain duplicate combinations.

Examples

Example 1

Input
candidates = [10, 1, 2, 7, 6, 1, 5], target = 8
Output
[[1,1,6],[1,2,5],[1,7],[2,6]]

Example 2

Input
candidates = [2, 5, 2, 1, 2], target = 5
Output
[[1,2,2],[5]]

Constraints

  • 1 <= candidates.length <= 100, values from 1 to 50
  • 1 <= target <= 30
  • Each element is used at most once; the input may have duplicates.

Animated walkthrough

A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.

Concepts first, then the problem and every approach, step by step.

Space to play or pause · ← → to jump a step · click or drag the bar to seek

Solutions

Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.

ApproachTimeSpace
Generate and deduplicateO(n · 2ⁿ)O(n · 2ⁿ)
Optimal (sort, skip equal siblings, break early)O(n · 2ⁿ)O(n)

1Generate and deduplicate

TimeO(n · 2ⁿ)
SpaceO(n · 2ⁿ)

Sort, run pick / not-pick with each element at most once, and store results in a set.

  1. Sort; pick / not-pick; add successful paths to a HashSet.
Java
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        Set<List<Integer>> seen = new HashSet<>();
        go(candidates, 0, target, new ArrayList<>(), seen);
        return new ArrayList<>(seen);
    }

    private void go(int[] c, int i, int target, List<Integer> path, Set<List<Integer>> seen) {
        if (target == 0) { seen.add(new ArrayList<>(path)); return; }
        if (i == c.length || target < 0) return;
        path.add(c[i]);
        go(c, i + 1, target - c[i], path, seen);
        path.remove(path.size() - 1);
        go(c, i + 1, target, path, seen);
    }
}

2Optimal (sort, skip equal siblings, break early)

TimeO(n · 2ⁿ)
SpaceO(n)

Sort. Loop from start; skip c[i] when it equals c[i - 1] at the same level (i > start); break once c[i] exceeds the remaining target; recurse with i + 1 so each element is used once.

  1. for i from start: if i > start && c[i] == c[i - 1], continue.
  2. if c[i] > target, break.
  3. Add, recurse(i + 1, target - c[i]), remove.
Java
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> out = new ArrayList<>();
        go(candidates, 0, target, new ArrayList<>(), out);
        return out;
    }

    private void go(int[] c, int start, int target, List<Integer> path, List<List<Integer>> out) {
        if (target == 0) { out.add(new ArrayList<>(path)); return; }
        for (int i = start; i < c.length; i++) {
            if (i > start && c[i] == c[i - 1]) continue;
            if (c[i] > target) break;
            path.add(c[i]);
            go(c, i + 1, target - c[i], path, out);
            path.remove(path.size() - 1);
        }
    }
}

Edge cases to test

  • Many equal values
  • No combination possible

Hints

Hint 1

This is Subsets II plus a target sum: sort, skip equal siblings, recurse with i + 1.

FAQ

What is the best time complexity for Combination Sum II?

Optimal (sort, skip equal siblings, break early) runs in O(n · 2ⁿ) time and O(n) extra space.

Which pattern does Combination Sum II use?

It is a recursion & backtracking problem that uses the pick / not-pick pattern. Other problems with the same pattern: Generate all binary strings without consecutive 1's, Subsets (2 choices per element), Subsets II.

Is there a brute force solution for Combination Sum II?

Yes. Generate and deduplicate takes O(n · 2ⁿ) time and O(n · 2ⁿ) space. Sort, run pick / not-pick with each element at most once, and store results in a set.

Which edge cases should I test for Combination Sum II?

Many equal values; No combination possible.