Finding all possible unique combinations of numbers to reach a given sum

319 Views Asked by At

We have a list of numbers, let's say: [ 2, 3, 5 ] and we have a targetSum, let's say: 8

Our goal, then, is to pick numbers from the list in such a way that the sum of the numbers would lead to targetSum

I'll explain my code first, I wrote a simple c++ code for the same, it uses recursion and backtracking ( without memoization ). It does the following:

  • We subdivide our original problem by reducing the targetSum by each number at each recursion
  • Visualizing this in the form of a tree is useful, we also keep track of what number's we have substracted so far, and we keep pushing and popping accordingly
  • Once we hit the base case of 0, meaning it's possible to create the sum, we make a note of the current numbers we have recursed
  • This process goes on until we have gone through all of the possibilities

Code:

#include<iostream>
#include<vector>

using namespace std;

bool bestSum( int targetSum, vector<int> &holder, vector<vector<int>> &combinations, 
vector<int> &path )
{
    if( targetSum == 0 )
    {
        combinations.push_back( path );
        return true;
    }
    if( targetSum < 0 )
    {
        return false;
    }

    bool possible = false;

    for( int i = 0; i < holder.size(); i++ )
    {
        int remainder = targetSum - holder[i];
        path.push_back(holder[i]);
    
        cout << "After pushing:";
        for( int j = 0; j < path.size(); j++ )
        {
            cout << path[j] << " ";
        }
        cout << endl;
    
        bool verdict = bestSum( remainder, holder, combinations, path );
        if( verdict == true )
        {
            possible = true;
        }
    
        path.pop_back();
        cout << "After popping:";
        for( int j = 0; j < path.size(); j++ )
        {
            cout << path[j] << " ";
        }
        cout << endl;
    
    }

    return possible;
}

int main()
{
    vector<int> holder = { 2, 3, 5 };
    int targetSum = 8;

    vector<vector<int>> combinations;
    vector<int> path;

    bool verdict = bestSum( targetSum, holder, combinations, path );

    for( int i = 0; i < combinations.size(); i++ )
    {
        for( int j = 0; j < combinations[i].size();j++)
        {
            cout << combinations[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

(ignoring the printing statements) Talking about time complexity, it should be: exponential, without memoization And at most small degree polynomial, with memoization

Combing back to the original problem, currently my code produces all of the possible combinations, for example, with the numbers list and targetSum presented at the start of this article, we would get: 2,3,3 and 3,3,2 as two different combinations. But we know that they aren't unique

My question is, is it possible to find all unique combination of numbers whilst keeping the logic of my code consistent?

0

There are 0 best solutions below