Find all distinct subset (or subsequence) sums of an array

3.1

Given a set of integers, find distinct sum that can be generated from the subsets of the given sets and print them in an increasing order. It is given that sum of array elements is small.

Examples:

Input  : arr[] = {1, 2, 3}
Output : 0 1 2 3 4 5 6
Distinct subsets of given set are
{}, {1}, {2}, {3}, {1,2}, {2,3}, 
{1,3} and {1,2,3}.  Sums of these
subsets are 0, 1, 2, 3, 3, 5, 4, 6
After removing duplicates, we get
0, 1, 2, 3, 4, 5, 6  

Input : arr[] = {2, 3, 4, 5, 6}
Output : 0 2 3 4 5 6 7 8 9 10 11 12 
         13 14 15 16 17 18 20

Input : arr[] = {20, 30, 50}
Output : 0 20 30 50 70 80 100

The naive solution for this problem is to generate all the subsets, store their sums in a hash set and finally print all keys from hash set.

// C++ program to print distinct subset sums of
// a given array.
#include<bits/stdc++.h>
using namespace std;

// sum denotes the current sum of the subset
// currindex denotes the index we have reached in
// the given array
void distSumRec(int arr[], int n, int sum,
                int currindex, unordered_set<int> &s)
{
    if (currindex > n)
        return;

    if (currindex == n)
    {
        s.insert(sum);
        return;
    }

    distSumRec(arr, n, sum + arr[currindex],
                            currindex+1, s);
    distSumRec(arr, n, sum, currindex+1, s);
}

// This function mainly calls recursive function
// distSumRec() to generate distinct sum subsets.
// And finally prints the generated subsets.
void printDistSum(int arr[], int n)
{
    unordered_set<int> s;
    distSumRec(arr, n, 0, 0, s);

    // Print the result
    for (auto i=s.begin(); i!=s.end(); i++)
        cout << *i << " ";
}

// Driver code
int main()
{
    int arr[] = {2, 3, 4, 5, 6};
    int n = sizeof(arr)/sizeof(arr[0]);
    printDistSum(arr, n);
    return 0;
}

Output:

0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20

Time complexity of the above naive recursive approach is O(2n).

Time complexity of the above problem can be improved using Dynamic Programming, especially when sum of given elements is small. We can make a dp table with rows containing the size of the array and size of the column will be sum of all the elements in the array.

// C++ program to print distinct subset sums of
// a given array.
#include<bits/stdc++.h>
using namespace std;

// Uses Dynamic Programming to find distinct
// subset sums
void printDistSum(int arr[], int n)
{
    int sum = 0;
    for (int i=0; i<n; i++)
        sum += arr[i];

    // dp[i][j] would be true if arr[0..i-1] has
    // a subset with sum equal to j.
    bool dp[n+1][sum+1];
    memset(dp, 0, sizeof(dp));

    // There is always a subset with 0 sum
    for (int i=0; i<=n; i++)
        dp[i][0] = true;

    // Fill dp[][] in bottom up manner
    for (int i=1; i<=n; i++)
    {
        dp[i][arr[i-1]] = true;
        for (int j=1; j<=sum; j++)
        {
            // Sums that were achievable
            // without current array element
            if (dp[i-1][j] == true)
            {
                dp[i][j] = true;
                dp[i][j + arr[i-1]] = true;
            }
        }
    }

    // Print last row elements
    for (int j=0; j<=sum; j++)
        if (dp[n][j]==true)
            cout << j << " ";
}


// Driver code
int main()
{
    int arr[] = {2, 3, 4, 5, 6};
    int n = sizeof(arr)/sizeof(arr[0]);
    printDistSum(arr, n);
    return 0;
}

Output:

0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20

Time complexity of the above approach is O(n*sum) where n is the size of the array and sum is the sum of all the integers in the array.

This article is contributed by Karan Goyal. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@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.

GATE CS Corner    Company Wise Coding Practice

Recommended Posts:



3.1 Average Difficulty : 3.1/5.0
Based on 11 vote(s)










Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.