Combination Sum

Question (LC.39)

Given an array of candidate numbers and a target, find all unique combinations from the candidate array that sum to the target.

Example

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

A candidate can be used unlimited number of times.

Analysis

Be careful with the input, it might contain duplicates. Step 1 Remove duplicates Step 2 Define DFS(parameter/return value, recursive calls, stop condition) Step 3 Write DFS

Code

Main function

/*
How is this different from subsets?
1. dup
2. use each number unlimited number of times
3. stop at a target
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
    List<List<Integer>> results = new ArrayList<>();
    if (candidates == null || candidates.length == 0) {
        return results;
    }
    Arrays.sort(candidates);
    combDFS(results, candidates, target, 0, new ArrayList<Integer>());
    return results;
}

DFS Search

We can improve a bit on the stopping conditions. We don't have to go down one more level until the target becomes negative. We can simply skip the candidates in the for loop that is bigger than the current target.

Combination Sums II (LC.40)

Approach

Analysis

dup doesn't change much right?

Consider this case

We want to keep [1,1,6] but get rid of [1,2,5], [1,7]. Essentially, we want to avoid using the second 1 as the root of the search. One may attempt if (i != 0 && candidates[i] == candidates[i-1]) continue;. But it gets rid of [1,1,6] as well. We want to only avoid duplicates on the same level so i != startIndex.

Code

The smart pruning will improve performance by a lot. It will bring the runtime from 21% to 93% on LC.

Combination Sum III (LC.216)

Find all possible combinations of k numbers that add up to a target. Only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Example

Always run examples FIRST. Running examples can give you another chance and read and understand the question better. It can also clarify the edge cases.

Analysis

We want to find all combinations 9 choose k, such that the combSum == target.

Approach

Code

Optimization

Adding this simple if statement will boost the performance from 12 to 58 percentile.

We can also do the pruning inside the for loop (save one level/stack frame more efficient)

Combination Sum IV (LC.377)

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example

Analysis

I originally thought this is combination with repetition. But the example shows [1,1,2], [1,2,1], and [2,1,1] are three different "combinations". In fact, under this definition, there's an infinite number of "combinations". For example, given a set [1,2,3], we can have {[1-3],[1-3],[1-3],[1-3], ...} so 3x3x3x3x3... number of combinations.

Brute Force Approach

find all combinations (where sum < target) add it to results if combSum == target

Code

But Time Limit Exceeded ٩ʕ•͡וʔ۶

Analysis 2

Draw the recursion tree and we can observe starting from [2] has overlapping subproblems as starting from [1].

DP Approach

In addition to the overlapping subproblems, the question is only asking for returning a count instead of a collection of all combinations. Also, it is unreasonable to search for all 181997601 combinations.

Top-Down (Memoization)

Now we can handle [1,2,3], 32 case. But [3,33,333], 10000 makes the program TLE again.

Updated Version (See comments above)

Bottom-Up (Tabulation)

Simplicity is harder to achieve than complexity.

Follow Up

What if negative numbers are allowed in the given array?

Then we need to add an extra constraint on the max length of a combination. Otherwise, we can run into the an infinite long combination such as [...,-1,-1,-1,1,1,1,...].

Reference

Combination Sum IV by Grand Yang

Last updated