Combination sum problem using JavaScript

The combination sum problem involves finding all unique combinations from a given array where the numbers sum to a target value. Each number can be used multiple times, making this a classic backtracking problem.

Problem Statement

Given a set of candidate numbers (without duplicates) and a target number, find all unique combinations where the candidate numbers sum to the target.

Constraints:

  • All numbers (including target) are positive integers

  • The same number may be chosen multiple times

  • The solution set must not contain duplicate combinations

Example:

Input: candidates = [2,3,6,7], target = 7

Output: [[7], [2,2,3]]

Algorithm Approach

Since we need all possible combinations, we use backtracking with recursion rather than dynamic programming. The algorithm explores each possibility and backtracks when a path doesn't lead to a solution.

Implementation

const recursiveSum = (
  candidates,
  remainingSum,
  finalCombinations = [],
  currentCombination = [],
  startFrom = 0,
) => {
  if (remainingSum < 0) {
    return finalCombinations;
  }
  if (remainingSum === 0) {
    finalCombinations.push(currentCombination.slice());
    return finalCombinations;
  }
  for (let candidateIndex = startFrom; candidateIndex < candidates.length; candidateIndex += 1) {
    const currentCandidate = candidates[candidateIndex];
    currentCombination.push(currentCandidate);
    recursiveSum(
      candidates,
      remainingSum - currentCandidate,
      finalCombinations,
      currentCombination,
      candidateIndex,
    );
    currentCombination.pop();
  }
  return finalCombinations;
}

const combinationSum = (candidates, target) => recursiveSum(candidates, target);

console.log(combinationSum([2, 3, 6, 7], 7));
console.log(combinationSum([2, 3, 5], 8));
[ [ 2, 2, 3 ], [ 7 ] ]
[ [ 2, 2, 2, 2 ], [ 2, 3, 3 ], [ 3, 5 ] ]

How It Works

The algorithm uses these key concepts:

  • Base Cases: If remaining sum is negative, return. If zero, we found a valid combination.

  • Backtracking: Try each candidate, recurse, then remove it to try other possibilities.

  • Avoid Duplicates: The startFrom parameter ensures we don't create duplicate combinations by only considering candidates from the current index onwards.

  • Reuse Numbers: Pass the same candidateIndex in recursion to allow reusing the current number.

Step-by-Step Example

For candidates = [2,3,6,7], target = 7:

// Trace through the algorithm
function traceExample() {
  console.log("Starting with candidates [2,3,6,7], target = 7");
  console.log("1. Try 2: remaining = 5, continue with 2");
  console.log("2. Try 2 again: remaining = 3, continue with 2");  
  console.log("3. Try 2 again: remaining = 1, continue with 2");
  console.log("4. Try 2 again: remaining = -1, backtrack");
  console.log("5. Try 3: remaining = 0, found combination [2,2,3]");
  console.log("6. Try 7: remaining = 0, found combination [7]");
  
  return combinationSum([2, 3, 6, 7], 7);
}

console.log("Final result:", traceExample());
Starting with candidates [2,3,6,7], target = 7
1. Try 2: remaining = 5, continue with 2
2. Try 2 again: remaining = 3, continue with 2
3. Try 2 again: remaining = 1, continue with 2
4. Try 2 again: remaining = -1, backtrack
5. Try 3: remaining = 0, found combination [2,2,3]
6. Try 7: remaining = 0, found combination [7]
Final result: [ [ 2, 2, 3 ], [ 7 ] ]

Time Complexity

The time complexity is approximately O(N^(T/M)) where N is the number of candidates, T is the target value, and M is the minimal value among the candidates. This represents exploring all possible combinations.

Conclusion

The combination sum problem is solved efficiently using backtracking with recursion. The key insight is using a startFrom parameter to avoid duplicate combinations while allowing number reuse.

Updated on: 2026-03-15T23:19:00+05:30

606 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements