Compile Ready
Module 4 · Combination Pattern

Combination Sum II

MediumProblem 7 of 17 10 min read ~23 min to solve LeetCode
BacktrackingRecursionDFSSortingDuplicate SkippingPruning
Asked atAmazonGoogleMicrosoftMetaBloomberg

Problem Statement

Given an array candidates that may contain duplicate positive integers and an integer target, return all unique combinations whose selected numbers sum to target. Each candidate occurrence may be used at most once. The answer must not contain duplicate combinations.

Input

An integer array candidates, possibly with duplicate values, and an integer target.

Output

A list of unique combinations where each array position is used at most once and each combination sums to target.

Constraints

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

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]]
Explanation: After sorting, the two **1** values can both be used in **[1,1,6]**, but duplicate branches that start with the second **1** at the same depth are skipped.

Example 2

Input:
candidates = [2,5,2,1,2], target = 5
Output: [[1,2,2],[5]]
Explanation: The three **2** values are separate occurrences, but the combination **[1,2,2]** appears only once.

Example 3

Input:
candidates = [1,1,1], target = 2
Output: [[1,1]]
Explanation: Multiple equal occurrences exist, but there is only one unique value combination that sums to 2.

Learning Objectives

  • Apply start-index recursion when each occurrence can be used at most once.
  • Sort the input so equal values become adjacent and can be skipped at the same depth.
  • Use **i > start && candidates[i] == candidates[i - 1]** to avoid duplicate combinations.
  • Prune target-sum branches with a sorted early break.

Intuition

Pattern Recognition

This is a combination sum with two added constraints: each array occurrence is one-use, and equal values can create duplicate result rows. The no-reuse part is solved by recursing with i + 1 after choosing index i. The duplicate part is solved by sorting and skipping equal values that would start the same choice at the same recursion depth.

The skip rule is depth-sensitive. If i > start and candidates[i] == candidates[i - 1], choosing this value would create the same subtree already created by the previous equal value at this depth. But when the previous equal value is already in the path from an earlier depth, the current equal value may still be chosen, which is how [1,1,6] remains valid.

Common mistakes

  • ×Skipping every duplicate value globally, which incorrectly prevents combinations such as **[1,1,6]**.
  • ×Using **i** instead of **i + 1** in the recursive call, which allows the same occurrence to be reused.
  • ×Applying the duplicate-skip rule before sorting the array.
  • ×Continuing after **candidate > remaining** even though the sorted suffix cannot help.

Algorithm Explanation

State

Each frame stores start, the first unused occurrence index available to this path, remaining, and path. Because each chosen occurrence advances to i + 1, no occurrence can be reused.

Recursion tree

For candidates = [10,1,2,7,6,1,5], sorting gives [1,1,2,5,6,7,10]. At the root, the first 1 opens all combinations beginning with 1, including the child that chooses the second 1 and later 6 to form [1,1,6]. When the root loop reaches the second 1, it is skipped because it would create another root subtree beginning with 1. Later, branches [1,2,5], [1,7], and [2,6] reach target 8. Values greater than the remaining sum stop their loops.

Pruning

Sort first. If i > start and the current value equals the previous value, skip it to avoid duplicate sibling branches. If candidates[i] > remaining, break because every later value is at least as large. If remaining == 0, add a copy of the path.

Algorithm

  1. Sort candidates.
  2. Start DFS with start = 0, remaining = target, and an empty path.
  3. If remaining == 0, add a copy of path.
  4. For each i from start onward, skip candidates[i] when it equals the previous value at the same depth.
  5. Break if candidates[i] > remaining.
  6. Choose candidates[i], recurse with start = i + 1, then unchoose it.

Solutions

Solution: Sorted one-use DFS with sibling duplicate skip

Sorting groups equal values together. The helper advances to i + 1 so each occurrence is used at most once, and the sibling skip removes duplicate subtrees without blocking valid repeated values across different depths.

Step-by-step

  1. Sort the candidate array so duplicates are adjacent.
  2. Start DFS with the full target as the remaining sum.
  3. At each depth, iterate from start to the end of the array.
  4. Skip a value if it equals the previous value and the previous value was a sibling choice at this same depth.
  5. Stop the loop once the value exceeds the remaining sum.
  6. Choose the value, recurse from index + 1, and then remove it.
Time

O(2^n * n)

Space

O(n)

In the worst case the DFS explores subsets of the n occurrences and copies length-n paths into the output. Sorting costs O(n log n).

Java implementation

Loading…

Dry Run

Sample input

candidates = [10,1,2,7,6,1,5], target = 8. After sorting, use [1,1,2,5,6,7,10].

depthstartchoicepath and sumaction
001 at index 0[1], remaining 7choose first 1
111 at index 1[1,1], remaining 6allowed because it is deeper, not a skipped sibling
226 at index 4[1,1,6], remaining 0add combination
112 at index 2[1,2], remaining 5choose 2 after first 1
235 at index 3[1,2,5], remaining 0add combination
117 at index 5[1,7], remaining 0add combination
001 at index 1[] remaining 8skip duplicate sibling because previous value was also 1
002 at index 2[2], remaining 6choose 2 from root
136 at index 4[2,6], remaining 0add combination
0010 at index 6[] remaining 8break because 10 exceeds remaining

The second 1 is skipped only as a root sibling. It is still available after choosing the first 1, which preserves valid combinations with repeated equal values.

Interview Tips

The duplicate skip is the centerpiece. Explain it as skipping duplicate siblings, not duplicate values everywhere. Use the phrase i > start to show that the previous equal value must be at the same recursion depth. Then contrast with Combination Sum: this problem advances to i + 1 because each occurrence is one-use.

Likely follow-ups

  • What breaks if the array is not sorted first?
  • How would you modify the solution to return combinations in descending order?
  • How would you count unique combinations without materialising them?
  • How does the skip rule differ from the one used in duplicate permutations?

Similar Problems

Key Takeaways

  • One-use candidates recurse with **i + 1**.
  • Sort duplicates before trying to skip them.
  • Skip equal sibling choices with **i > start** to avoid duplicate combinations.
  • A sorted early break cuts every suffix once the candidate exceeds the remaining target.
Reusable template: For one-use combination sums with duplicates, sort, recurse to the next index, skip equal sibling values, and break when the candidate is larger than the remaining target.