Combination Sum II – Find all unique combinations

Spread the love

We shall answer the most often requested interview question “Combination Sum II – Find all unique combinations” in this post.

Find all unique combinations in candidates where the candidate numbers add to target given a set of candidate numbers (candidates) and a target number. Every number in the candidates could just be used once in the mix.

Note: The set of solutions has to be devoid of repeating combinations.

Some instances are:

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: These are the unique combinations whose sum is equal to target.
 
Example 2:

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

Output: [[1,2,2],[5]]

Explanation: These are the unique combinations whose sum is equal to target.

Solution:

Disclaimer: Don’t jump directly to the solution, try it out yourself first.

Solution 1: Using extra space and time complexity 

Approach:

Defining the Recursive Function:

Sort the elements before beginning the recursive call; the ans should not be duplicated and should include the combinations in sorted sequence.

We begin with the index 0; at index 0 we have n – 1 ways to choose the first element of our subsequence.

See if our ds could benefit from the current index value. If so, include it into the ds and shift the index by one. As shifting the index skip the consecutive repeated elements will create duplicate sequences.

After the call make sure to pop the element from the ds. Reduce the target by arr[i] and call the recursive call for f(idx + 1,target – 1,ds,ans).(Seeing the example repeatedly will help you to grasp).

If arr[i] > target, then stop the recursive function since there is no need in checking; the index will be moving by 1 all the entries to its right will be in increasing order.

Base state:

Add the ds to the ans return anyhow the goal value is zero.

Recursive call represented for the provided example below:

Code

C++

from typing import List




def combinationSum2(candidates: List[int], target: int) -> List[List[int]]:
    ans = []
    ds = []
    candidates.sort()


    def findCombination(ind: int, target: int):
        if target == 0:
            ans.append(ds[:])
            return
        for i in range(ind, len(candidates)):
            if i > ind and candidates[i] == candidates[i - 1]:
                continue
            if candidates[i] > target:
                break
            ds.append(candidates[i])
            findCombination(i + 1, target - candidates[i])
            ds.pop()


    findCombination(0, target)
    return ans




if __name__ == "__main__":
    v = [10, 1, 2, 7, 6, 1, 5]
    comb = combinationSum2(v, 8)
    print(*comb)

Java

import java.util.*;
class TUF {
    static void findCombinations(int ind, int[] arr, int target, List < List < Integer >> ans, List < Integer > ds) {
        if (target == 0) {
            ans.add(new ArrayList < > (ds));
            return;
        }

        for (int i = ind; i < arr.length; i++) {
            if (i > ind && arr[i] == arr[i - 1]) continue;
            if (arr[i] > target) break;

            ds.add(arr[i]);
            findCombinations(i + 1, arr, target - arr[i], ans, ds);
            ds.remove(ds.size() - 1);
        }
    }
    public static List < List < Integer >> combinationSum2(int[] candidates, int target) {
        List < List < Integer >> ans = new ArrayList < > ();
        Arrays.sort(candidates);
        findCombinations(0, candidates, target, ans, new ArrayList < > ());
        return ans;
    }

    public static void main(String args[]) {
        int v[]={10,1,2,7,6,1,5};
        List < List < Integer >> comb = combinationSum2(v, 8);
        System.out.println(comb.toString().replace(",", " "));
    }
}

Python

from typing import List




def combinationSum2(candidates: List[int], target: int) -> List[List[int]]:
    ans = []
    ds = []
    candidates.sort()


    def findCombination(ind: int, target: int):
        if target == 0:
            ans.append(ds[:])
            return
        for i in range(ind, len(candidates)):
            if i > ind and candidates[i] == candidates[i - 1]:
                continue
            if candidates[i] > target:
                break
            ds.append(candidates[i])
            findCombination(i + 1, target - candidates[i])
            ds.pop()


    findCombination(0, target)
    return ans




if __name__ == "__main__":
    v = [10, 1, 2, 7, 6, 1, 5]
    comb = combinationSum2(v, 8)
    print(*comb)

Output:

[ [ 1 1 6 ][ 1 2 5 ][ 1 7 ][ 2 6 ] ]

Time Complexity:O(2^n*k)

Space Complexity:O(k*x)