Compile Ready
Module 4 · Combination Pattern

Combination Sum

MediumProblem 6 of 17 9 min read ~20 min to solve LeetCode
BacktrackingRecursionDFSArrayPruningCombinations
Asked atAmazonGoogleMicrosoftMetaAdobe

Problem Statement

Given an array of distinct positive integers candidates and a positive integer target, return all unique combinations of candidates whose selected numbers sum to target. You may choose the same candidate an unlimited number of times. The answer may be returned in any order.

Input

An integer array candidates containing distinct positive values, and an integer target.

Output

A list of combinations where each combination sums to target and may reuse a candidate multiple times.

Constraints

  • 1 <= candidates.length <= 30
  • 2 <= candidates[i] <= 40
  • All elements of candidates are distinct
  • 1 <= target <= 40

Examples

Example 1

Input:
candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]
Explanation: The value **2** can be reused, so **2 + 2 + 3** is valid. **7** alone is also valid.

Example 2

Input:
candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]
Explanation: Each listed combination sums to 8, and order variants such as **[3,2,3]** are not repeated.

Example 3

Input:
candidates = [2], target = 1
Output: []
Explanation: The only candidate already exceeds the target, so no combination exists.

Learning Objectives

  • Distinguish unlimited reuse from the no-reuse combination template.
  • Use the same **start** index after choosing a candidate that may be reused.
  • Sort candidates so **candidate > remaining** can end the loop early.
  • Track remaining target instead of recomputing the path sum from scratch.

Intuition

Pattern Recognition

This is still a choose-without-order problem: [2,2,3] and [3,2,2] represent the same combination. The start-index technique is still the right duplicate-prevention tool. The twist is reuse: after choosing candidate at index i, the next recursive call starts at i again, not i + 1.

Because every number is positive, the running sum only increases as the path grows. That gives a clean pruning rule: once the remaining target becomes negative, the branch cannot recover. Sorting improves the rule further: when the current candidate is larger than the remaining target, all later candidates are also too large, so the loop can break.

Common mistakes

  • ×Recursing with **i + 1** after every choice, which incorrectly forbids using a candidate more than once.
  • ×Recursing from **0** after every choice, which creates duplicate orderings of the same combination.
  • ×Continuing the loop after a sorted candidate exceeds the remaining target.
  • ×Adding a path when the sum is below target just because no more candidates were tried.

Algorithm Explanation

State

Each frame carries start, the first candidate index allowed in this combination suffix, remaining, the amount still needed to reach target, and path, the chosen values.

Recursion tree

For sorted [2,3,6,7] and target 7, the root first chooses 2 and stays at index 0, allowing another 2. That path reaches [2,2] with remaining 3, then chooses 3 and adds [2,2,3]. The branch [2,2,2] has remaining 1, so candidates 2, 3, 6, and 7 are too large and the branch stops. Back at the root, choosing 3 cannot later choose 2, so order duplicates are avoided. Choosing 7 reaches remaining 0 and adds [7].

Pruning

All values are positive. If remaining == 0, the path is complete. If a sorted candidate is greater than remaining, break the loop because all later candidates are greater too. Reusing is controlled deliberately by calling the helper with the same index i.

Algorithm

  1. Sort candidates.
  2. Start DFS with start = 0, remaining = target, and an empty path.
  3. If remaining == 0, copy path into the answer.
  4. Loop i from start to the end of the array.
  5. Break when candidates[i] > remaining.
  6. Choose candidates[i], recurse with start = i and the reduced remaining target, then unchoose it.

Solutions

Solution: Sorted start-index DFS with reusable candidates

Sorting lets the DFS stop a branch as soon as a candidate is too large for the remaining target. Passing i back into the recursive call is the key reuse rule; passing i + 1 would solve a different problem.

Step-by-step

  1. Sort the candidates in ascending order.
  2. Call the helper with start index 0 and the full target as the remaining sum.
  3. When remaining becomes 0, copy the current path into the result.
  4. For each candidate from start onward, stop if it exceeds the remaining sum.
  5. Add the candidate, recurse from the same index to allow reuse, then remove it before trying the next candidate.
Time

O(n^(target / minCandidate) * target / minCandidate)

Space

O(target / minCandidate)

The maximum depth is bounded by repeatedly choosing the smallest candidate. The output size dominates for many inputs.

Java implementation

Loading…

Dry Run

Sample input

candidates = [2,3,6,7], target = 7. The array is already sorted. Track remaining as part of the path summary.

depthstartchoicepath and sumaction
002[2], remaining 5choose 2 and recurse from same index 0
102[2,2], remaining 3reuse 2 because start stayed at 0
202[2,2,2], remaining 1next candidate 2 is too large, prune
203[2,2,3], remaining 0add combination
103[2,3], remaining 2candidate 3 is now too large at next depth, prune
003[3], remaining 4choose 3, recurse from index 1
113[3,3], remaining 1candidate 3 is too large, prune
006[6], remaining 1next candidate 6 is too large, prune
007[7], remaining 0add combination

The same-index recursive call is why 2 can repeat, while the start index still prevents order duplicates like [3,2,2].

Interview Tips

Frame the problem as combinations over a sorted candidate list, not permutations. Then explicitly say the recursive start rule: reuse means call with i; no reuse means call with i + 1. That single sentence often separates correct solutions from near misses.

Likely follow-ups

  • What changes if each candidate may be used at most once?
  • How would you handle duplicate values in **candidates**?
  • How would you return only the number of combinations instead of listing them?
  • How would the solution change if negative numbers were allowed?

Similar Problems

Key Takeaways

  • Unlimited reuse means recurse from the same candidate index.
  • The start index still prevents permuted duplicates.
  • Sorting enables an early break when a candidate exceeds the remaining target.
  • Track **remaining** directly so the base case is **remaining == 0**.
Reusable template: For reusable combination sums, sort candidates, recurse from the same index after choosing, and stop a loop branch once the candidate exceeds the remaining target.