Skip to content
Related Articles

Related Articles

Combinational Sum

View Discussion
Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 22 Sep, 2022
View Discussion
Improve Article
Save Article

Given an array of positive integers arr[] and an integer x, The task is to find all unique combinations in arr[] where the sum is equal to x. 
The same repeated number may be chosen from arr[] an unlimited number of times. Elements in a combination (a1, a2, …, ak) must be printed in non-descending order. (ie, a1 <= a2 <= … <= ak). If there is no combination possible print “Empty”.

Examples: 

Input: arr[] = 2, 4, 6, 8, x = 8
Output: 
[2, 2, 2, 2]
[2, 2, 4]
[2, 6]
[4, 4]
[8]

Approach:

Recursively find all combinations and if the current combination sums up to give X then add this combination in the final set of combinations.

Follow the below steps to implement the idea:

  • Sort the array arr[] and remove all the duplicates from the arr[] then create a temporary vector r. to store every combination and a vector of vector res.
  • Recursively follow: 
    • If at any time sub-problem sum == 0 then add that array to the res (vector of vectors).
    • Run a while loop till the sum – arr[I] is not negative and i is less than arr.size().
      • Push arr[i] in r and recursively call for i and sum-arr[i] ,then increment i by 1.
      • pop r[i] from back and backtrack. 

Below is the implementation of the above approach.

C++




// C++ program to find all combinations that
// sum to a given value
#include <bits/stdc++.h>
using namespace std;
 
// Print all members of ar[] that have given
void findNumbers(vector<int>& ar, int sum,
                 vector<vector<int> >& res, vector<int>& r,
                 int i)
{
    // if we get exact answer
    if (sum == 0) {
        res.push_back(r);
        return;
    }
 
    // Recur for all remaining elements that
    // have value smaller than sum.
    while (i < ar.size() && sum - ar[i] >= 0) {
 
        // Till every element in the array starting
        // from i which can contribute to the sum
        r.push_back(ar[i]); // add them to list
 
        // recursive call for next numbers
        findNumbers(ar, sum - ar[i], res, r, i);
        i++;
 
        // Remove number from list (backtracking)
        r.pop_back();
    }
}
 
// Returns all combinations
// of ar[] that have given
// sum.
vector<vector<int> > combinationSum(vector<int>& ar,
                                    int sum)
{
    // sort input array
    sort(ar.begin(), ar.end());
 
    // remove duplicates
    ar.erase(unique(ar.begin(), ar.end()), ar.end());
 
    vector<int> r;
    vector<vector<int> > res;
    findNumbers(ar, sum, res, r, 0);
 
    return res;
}
 
// Driver code
int main()
{
    vector<int> ar;
    ar.push_back(2);
    ar.push_back(4);
    ar.push_back(6);
    ar.push_back(8);
    int n = ar.size();
 
    int sum = 8; // set value of sum
    vector<vector<int> > res = combinationSum(ar, sum);
 
    // If result is empty, then
    if (res.size() == 0) {
        cout << "Empty";
        return 0;
    }
 
    // Print all combinations stored in res.
    for (int i = 0; i < res.size(); i++) {
        if (res[i].size() > 0) {
            cout << " ( ";
            for (int j = 0; j < res[i].size(); j++)
                cout << res[i][j] << " ";
            cout << ")";
        }
    }
  return 0;
}


Java




// Java program to find all combinations that
// sum to a given value
import java.io.*;
import java.util.*;
 
class GFG {
 
    static ArrayList<ArrayList<Integer> >
    combinationSum(ArrayList<Integer> arr, int sum)
    {
        ArrayList<ArrayList<Integer> > ans
            = new ArrayList<>();
        ArrayList<Integer> temp = new ArrayList<>();
 
        // first do hashing since hashset does not always
        // sort
        //  removing the duplicates using HashSet and
        // Sorting the arrayList
 
        Set<Integer> set = new HashSet<>(arr);
        arr.clear();
        arr.addAll(set);
        Collections.sort(arr);
 
        findNumbers(ans, arr, sum, 0, temp);
        return ans;
    }
 
    static void
    findNumbers(ArrayList<ArrayList<Integer> > ans,
                ArrayList<Integer> arr, int sum, int index,
                ArrayList<Integer> temp)
    {
 
        if (sum == 0) {
 
            // Adding deep copy of list to ans
 
            ans.add(new ArrayList<>(temp));
            return;
        }
 
        for (int i = index; i < arr.size(); i++) {
 
            // checking that sum does not become negative
 
            if ((sum - arr.get(i)) >= 0) {
 
                // adding element which can contribute to
                // sum
 
                temp.add(arr.get(i));
 
                findNumbers(ans, arr, sum - arr.get(i), i,
                            temp);
 
                // removing element from list (backtracking)
                temp.remove(arr.get(i));
            }
        }
    }
 
    // Driver Code
 
    public static void main(String[] args)
    {
        ArrayList<Integer> arr = new ArrayList<>();
 
        arr.add(2);
        arr.add(4);
        arr.add(6);
        arr.add(8);
 
        int sum = 8;
 
        ArrayList<ArrayList<Integer> > ans
            = combinationSum(arr, sum);
 
        // If result is empty, then
        if (ans.size() == 0) {
            System.out.println("Empty");
            return;
        }
 
        // print all combinations stored in ans
 
        for (int i = 0; i < ans.size(); i++) {
 
            System.out.print("(");
            for (int j = 0; j < ans.get(i).size(); j++) {
                System.out.print(ans.get(i).get(j) + " ");
            }
            System.out.print(") ");
        }
    }
}


Python3




# Python3 program to find all combinations that
# sum to a given value
 
def combinationSum(arr, sum):
    ans = []
    temp = []
 
    # first do hashing nothing but set{}
    # since set does not always sort
    # removing the duplicates using Set and
    # Sorting the List
    arr = sorted(list(set(arr)))
    findNumbers(ans, arr, temp, sum, 0)
    return ans
 
def findNumbers(ans, arr, temp, sum, index):
     
    if(sum == 0):
         
        # Adding deep copy of list to ans
        ans.append(list(temp))
        return
       
    # Iterate from index to len(arr) - 1
    for i in range(index, len(arr)):
 
        # checking that sum does not become negative
        if(sum - arr[i]) >= 0:
 
            # adding element which can contribute to
            # sum
            temp.append(arr[i])
            findNumbers(ans, arr, temp, sum-arr[i], i)
 
            # removing element from list (backtracking)
            temp.remove(arr[i])
 
 
# Driver Code
arr = [2, 4, 6, 8]
sum = 8
ans = combinationSum(arr, sum)
 
# If result is empty, then
if len(ans) <= 0:
    print("empty")
     
# print all combinations stored in ans
for i in range(len(ans)):
 
    print("(", end=' ')
    for j in range(len(ans[i])):
        print(str(ans[i][j])+" ", end=' ')
    print(")", end=' ')
 
 
# This Code Is Contributed by Rakesh(vijayarigela09)


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
using System.Collections;
 
class GFG {
 
    static List<List<int> >
    combinationSum(List<int> arr, int sum)
    {
        List<List<int> > ans
            = new List<List<int> >();
        List<int> temp = new List<int>();
 
        // first do hashing since hashset does not always
        // sort
        //  removing the duplicates using HashSet and
        // Sorting the List
 
        HashSet<int> set = new HashSet<int>(arr);
        arr.Clear();
        arr.AddRange(set);
        arr.Sort();
 
        findNumbers(ans, arr, sum, 0, temp);
        return ans;
    }
 
    static void
    findNumbers(List<List<int> > ans,
                List<int> arr, int sum, int index,
                List<int> temp)
    {
 
        if (sum == 0) {
 
            // Adding deep copy of list to ans
 
            ans.Add(new List<int>(temp));
            return;
        }
 
        for (int i = index; i < arr.Count; i++) {
 
            // checking that sum does not become negative
 
            if ((sum - arr[i]) >= 0) {
 
                // Adding element which can contribute to
                // sum
 
                temp.Add(arr[i]);
 
                findNumbers(ans, arr, sum - arr[i], i,
                            temp);
 
                // removing element from list (backtracking)
                temp.Remove(arr[i]);
            }
        }
    }
 
    // Driver Code
 
    public static void Main()
    {
        List<int> arr = new List<int>();
         
        arr.Add(2);
        arr.Add(4);
        arr.Add(6);
        arr.Add(8);
 
        int sum = 8;
 
        List<List<int> > ans
            = combinationSum(arr, sum);
 
        // If result is empty, then
        if (ans.Count == 0) {
            Console.WriteLine("Empty");
            return;
        }
 
        // print all combinations stored in ans
 
        for (int i = 0; i < ans.Count; i++) {
 
            Console.Write("(");
            for (int j = 0; j < ans[i].Count; j++) {
                Console.Write(ans[i][j] + " ");
            }
            Console.Write(") ");
        }
    }
}
 
// This code is contributed by ShubhamSingh10


Javascript




<script>
// Javascript program to find all combinations that
// sum to a given value
 
function combinationSum(arr, sum) {
    let ans = new Array();
    let temp = new Array();
 
    // first do hashing since hashset does not always
    // sort
    //  removing the duplicates using HashSet and
    // Sorting the arrayList
 
    let set = new Set([...arr]);
    arr = [...set];
    arr.sort()
 
    findNumbers(ans, arr, sum, 0, temp);
    return ans;
}
 
function findNumbers(ans, arr, sum, index, temp) {
 
    if (sum == 0) {
 
        // pushing deep copy of list to ans
 
        ans.push([...temp]);
        return;
    }
 
    for (let i = index; i < arr.length; i++) {
 
        // checking that sum does not become negative
 
        if ((sum - arr[i]) >= 0) {
 
            // pushing element which can contribute to
            // sum
 
            temp.push(arr[i]);
 
            findNumbers(ans, arr, sum - arr[i], i, temp);
 
            // removing element from list (backtracking)
            temp.splice(temp.indexOf(arr[i]), 1);
        }
    }
}
 
// Driver Code
 
 
let arr = []
 
arr.push(2);
arr.push(4);
arr.push(6);
arr.push(8);
 
let sum = 8;
 
let ans = combinationSum(arr, sum);
 
// If result is empty, then
if (ans.length == 0) {
    document.write("Empty");
}
 
// print all combinations stored in ans
for (let i = 0; i < ans.length; i++) {
 
    document.write("(");
    for (let j = 0; j < ans[i].length; j++) {
        document.write(" ", ans[i][j] + " ");
    }
    document.write(") ");
}
 
// This code is contributed by saurabh_jaiswal.
</script>


Output

 ( 2 2 2 2 ) ( 2 2 4 ) ( 2 6 ) ( 4 4 ) ( 8 )

Time Complexity: O(n2), where n is the size of array.
Auxiliary Space: O(n2)

This article is contributed by Aditya Nihal Kumar Singh. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!