All distinct subset (or subsequence) sums of an array

Last Updated : 12 Sep, 2026

Given an array arr[] of integers, generate all possible distinct subset (or subsequence) sums and return in sorted order.

A subset may contain any number of elements, including the empty subset.

Examples:  

Input: arr[] = [1, 2]
Output: [0, 1, 2, 3]
Explanation: Four distinct sums can be calculated which are 0, 1, 2 and 3.

  • 0 if we do not choose any number.
  • 1 if we choose only 1.
  • 2 if we choose only 2.
  • 3 if we choose 1 and 2.

Input: arr[] = [1, 2, 3]
Output: [0, 1, 2, 3, 4, 5, 6]
Explanation: Seven distinct sums can be calculated which are 0, 1, 2, 3, 4, 5 and 6.

  • 0 if we do not choose any number.
  • 1 if we choose only 1.
  • 2 if we choose only 2.
  • 3 if we choose only 3.
  • 4 if we choose 1 and 3.
  • 5 if we choose 2 and 3.
  • 6 if we choose 1, 2 and 3.
Try It Yourself
redirect icon

[Naive Approach] Using Recursion – O(2^n) Time and O(n) Space

We generate all subsets, store their sums in a hash set and finally return all keys from the hash set. recursively generates all possible subset sums by considering each element twice - once including it in the sum and once excluding it. When index is reached at n store the current sum to hashSet and return.

  • Include the current element (arr[i]) in the subset sum: distSumRec(arr, n, sum + arr[i], i + 1, s)
  • Exclude the current element from the subset sum: distSumRec(arr, n, sum, i + 1, s)
C++
#include <bits/stdc++.h>
using namespace std;

void distSumRec(vector<int> &arr, int n, int sum,
                int i, set<int> &s) {
    if (i > n)
        return;

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

    // Include the current element
    distSumRec(arr, n, sum + arr[i], i + 1, s);

    // Exclude the current element
    distSumRec(arr, n, sum, i + 1, s);
}

vector<int> distinctSum(vector<int> &arr) {
    set<int> s;
    int n = arr.size();

    distSumRec(arr, n, 0, 0, s);

    vector<int> result;
    for (int x : s)
        result.push_back(x);

    return result;
}

int main() {
    vector<int> arr = {2, 3, 4, 5, 6};

    vector<int> result = distinctSum(arr);

    cout << "[";
    for (int i = 0; i < result.size(); i++) {
        cout << result[i];
        if (i + 1 < result.size())
            cout << ", ";
    }
    cout << "]";

    return 0;
}
Java
import java.util.Set;
import java.util.TreeSet;
import java.util.ArrayList;

class GFG {

    static void distSumRec(int[] arr, int n, int sum,
                           int i, Set<Integer> s) {
        if (i > n)
            return;

        if (i == n) {
            s.add(sum);
            return;
        }

        // Include the current element
        distSumRec(arr, n, sum + arr[i], i + 1, s);

        // Exclude the current element
        distSumRec(arr, n, sum, i + 1, s);
    }

    static ArrayList<Integer> distinctSum(int[] arr) {
        Set<Integer> s = new TreeSet<>();
        int n = arr.length;

        distSumRec(arr, n, 0, 0, s);

        return new ArrayList<>(s);
    }

    static void printList(ArrayList<Integer> result) {
        System.out.print("[");
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i));
            if (i + 1 < result.size())
                System.out.print(", ");
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        int[] arr = {2, 3, 4, 5, 6};

        ArrayList<Integer> result = distinctSum(arr);
        printList(result);
    }
}
Python
def distSumRec(arr, n, sum_val, i, s):
    if i > n:
        return

    if i == n:
        s.add(sum_val)
        return

    # Include the current element
    distSumRec(arr, n, sum_val + arr[i], i + 1, s)

    # Exclude the current element
    distSumRec(arr, n, sum_val, i + 1, s)


def distinctSum(arr):
    s = set()
    n = len(arr)

    distSumRec(arr, n, 0, 0, s)

    return sorted(s)


if __name__ == "__main__":
    arr = [2, 3, 4, 5, 6]

    result = distinctSum(arr)

    print("[" + ", ".join(map(str, result)) + "]")
C#
using System;
using System.Collections.Generic;

class GFG {

    static void distSumRec(List<int> arr, int n, int sum,
                           int i, HashSet<int> s) {
        if (i > n)
            return;

        if (i == n) {
            s.Add(sum);
            return;
        }

        // Include the current element
        distSumRec(arr, n, sum + arr[i], i + 1, s);

        // Exclude the current element
        distSumRec(arr, n, sum, i + 1, s);
    }

    static List<int> distinctSum(List<int> arr) {
        HashSet<int> s = new HashSet<int>();
        int n = arr.Count;

        distSumRec(arr, n, 0, 0, s);

        List<int> result = new List<int>(s);
        result.Sort();

        return result;
    }

    static void Main() {
        List<int> arr = new List<int> { 2, 3, 4, 5, 6 };

        List<int> result = distinctSum(arr);

        Console.WriteLine("[" + string.Join(", ", result) + "]");
    }
}
JavaScript
function distSumRec(arr, n, sum, i, s) {
    if (i > n)
        return;

    if (i === n) {
        s.add(sum);
        return;
    }

    // Include the current element
    distSumRec(arr, n, sum + arr[i], i + 1, s);

    // Exclude the current element
    distSumRec(arr, n, sum, i + 1, s);
}

function distinctSum(arr) {
    let s = new Set();
    let n = arr.length;

    distSumRec(arr, n, 0, 0, s);

    return [...s].sort((a, b) => a - b);
}

// Driver Code
let arr = [2, 3, 4, 5, 6];

let result = distinctSum(arr);

console.log("[" + result.join(", ") + "]");

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

[Better Approach 1] Memoization - O(n * sum) Time and O(n * sum) Space

If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming.

The subproblems in the above recursive solution overlap because the same subset sums are computed multiple times during recursion. For example, when considering an element in the set, the same sum can be encountered in different recursive calls.

  • We create a 2D memoization table memo[n+1][totalSum+1] where n is the number of elements in the array and totalSum is the sum of all the elements in the array. Each entry memo[i][sum] will store whether the sum sum can be formed by the first i elements of the array.
  • Initially, all entries are set to -1 to indicate that no subproblems have been computed yet.
  • Before computing memo[i][sum], we check if it is already computed by checking if memo[i][sum] != -1. If it's already computed, we return the stored result; otherwise, we calculate it recursively using the inclusion/exclusion approach.
C++
#include <bits/stdc++.h>
using namespace std;

// Recursive function to calculate distinct subset sums
void distSumRec(vector<int> &arr, int n, int sum,
                int i, vector<vector<int>> &memo) {
    if (i == n) {
        memo[i][sum] = 1;
        return;
    }

    if (memo[i][sum] != -1)
        return;

    // Mark the current state as visited
    memo[i][sum] = 1;

    // Include the current element
    distSumRec(arr, n, sum + arr[i], i + 1, memo);

    // Exclude the current element
    distSumRec(arr, n, sum, i + 1, memo);
}

// Generate distinct subset sums using memoization
vector<int> distinctSum(vector<int> &arr) {
    int n = arr.size();
    int totalSum = accumulate(arr.begin(), arr.end(), 0);

    vector<vector<int>> memo(
        n + 1, vector<int>(totalSum + 1, -1)
    );

    distSumRec(arr, n, 0, 0, memo);

    vector<int> result;

    for (int sum = 0; sum <= totalSum; sum++) {
        if (memo[n][sum] == 1)
            result.push_back(sum);
    }

    return result;
}

int main() {
    vector<int> arr = {2, 3, 4, 5, 6};

    vector<int> result = distinctSum(arr);

    cout << "[";
    for (int i = 0; i < result.size(); i++) {
        cout << result[i];
        if (i + 1 < result.size())
            cout << ", ";
    }
    cout << "]";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

class GFG {

    // Recursive function to calculate distinct subset sums
    static void distSumRec(int[] arr, int n, int sum,
                           int i, int[][] memo) {
        if (i == n) {
            memo[i][sum] = 1;
            return;
        }

        if (memo[i][sum] != -1)
            return;

        // Mark the current state as visited
        memo[i][sum] = 1;

        // Include the current element
        distSumRec(arr, n, sum + arr[i], i + 1, memo);

        // Exclude the current element
        distSumRec(arr, n, sum, i + 1, memo);
    }

    // Generate distinct subset sums using memoization
    static ArrayList<Integer> distinctSum(int[] arr) {
        int n = arr.length;
        int totalSum = 0;

        for (int x : arr)
            totalSum += x;

        int[][] memo = new int[n + 1][totalSum + 1];

        for (int[] row : memo)
            Arrays.fill(row, -1);

        distSumRec(arr, n, 0, 0, memo);

        ArrayList<Integer> result = new ArrayList<>();

        for (int sum = 0; sum <= totalSum; sum++) {
            if (memo[n][sum] == 1)
                result.add(sum);
        }

        return result;
    }

    static void printList(ArrayList<Integer> result) {
        System.out.print("[");
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i));
            if (i + 1 < result.size())
                System.out.print(", ");
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        int[] arr = {2, 3, 4, 5, 6};

        ArrayList<Integer> result = distinctSum(arr);

        printList(result);
    }
}
Python
def distSumRec(arr, n, sum_val, i, memo):
    if i == n:
        memo[i][sum_val] = 1
        return

    if memo[i][sum_val] != -1:
        return

    # Mark the current state as visited
    memo[i][sum_val] = 1

    # Include the current element
    distSumRec(arr, n, sum_val + arr[i], i + 1, memo)

    # Exclude the current element
    distSumRec(arr, n, sum_val, i + 1, memo)


# Generate distinct subset sums using memoization
def distinctSum(arr):
    n = len(arr)
    total_sum = sum(arr)

    memo = [[-1] * (total_sum + 1) for _ in range(n + 1)]

    distSumRec(arr, n, 0, 0, memo)

    result = []

    for sum_val in range(total_sum + 1):
        if memo[n][sum_val] == 1:
            result.append(sum_val)

    return result


if __name__ == "__main__":
    arr = [2, 3, 4, 5, 6]

    result = distinctSum(arr)

    print("[" + ", ".join(map(str, result)) + "]")
C#
using System;
using System.Collections.Generic;

class GFG {

    // Recursive function to calculate distinct subset sums
    static void distSumRec(List<int> arr, int n, int sum,
                           int i, int[,] memo) {
        if (i == n) {
            memo[i, sum] = 1;
            return;
        }

        if (memo[i, sum] != -1)
            return;

        // Mark the current state as visited
        memo[i, sum] = 1;

        // Include the current element
        distSumRec(arr, n, sum + arr[i], i + 1, memo);

        // Exclude the current element
        distSumRec(arr, n, sum, i + 1, memo);
    }

    // Generate distinct subset sums using memoization
    static List<int> distinctSum(List<int> arr) {
        int n = arr.Count;
        int totalSum = 0;

        foreach (int x in arr)
            totalSum += x;

        int[,] memo = new int[n + 1, totalSum + 1];

        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= totalSum; j++)
                memo[i, j] = -1;
        }

        distSumRec(arr, n, 0, 0, memo);

        List<int> result = new List<int>();

        for (int sum = 0; sum <= totalSum; sum++) {
            if (memo[n, sum] == 1)
                result.Add(sum);
        }

        return result;
    }

    static void Main() {
        List<int> arr = new List<int> { 2, 3, 4, 5, 6 };

        List<int> result = distinctSum(arr);

        Console.WriteLine("[" + string.Join(", ", result) + "]");
    }
}
JavaScript
function distSumRec(arr, n, sum, i, memo, totalSum) {
    let index = i * (totalSum + 1) + sum;

    if (i === n) {
        memo[index] = 1;
        return;
    }

    if (memo[index] === 1)
        return;

    // Mark the current state as visited
    memo[index] = 1;

    // Include the current element
    distSumRec(
        arr, n, sum + arr[i], i + 1, memo, totalSum
    );

    // Exclude the current element
    distSumRec(
        arr, n, sum, i + 1, memo, totalSum
    );
}

// Generate distinct subset sums using memoization
function distinctSum(arr) {
    let n = arr.length;
    let totalSum = arr.reduce((a, b) => a + b, 0);

    let memo = new Int8Array(
        (n + 1) * (totalSum + 1)
    );

    distSumRec(arr, n, 0, 0, memo, totalSum);

    let result = [];

    for (let sum = 0; sum <= totalSum; sum++) {
        let index = n * (totalSum + 1) + sum;

        if (memo[index] === 1)
            result.push(sum);
    }

    return result;
}

// Driver Code
let arr = [2, 3, 4, 5, 6];

let result = distinctSum(arr);

console.log("[" + result.join(", ") + "]");

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

[Better Approach 2] Tabulation – O(n * sum) Time and O(n * sum) Space

The approach is similar to the previous one. just instead of breaking down the problem recursively, we iteratively build up the solution by calculating in bottom-up manner.

We will create a 2D array dp[][] of size (n + 1) x (sum + 1) where sum is the sum of all elements in the array. Each dp[i][j] represents whether a subset of the first i elements of the array can sum to j. dp[i][j] = true means that there is a subset of elements from arr[0..i-1] that sums to j.

Base case:

  • We always have a subset with sum 0, which is the empty subset. Therefore, we initialize the first column dp[i][0] = true for all i, as the sum of 0 is always achievable with the empty subset.

For every element arr[i-1], we will either include or exclude it in the subset sum, and update the table accordingly.

  • Including the Element: If we include arr[i-1], then the new sum becomes j + arr[i-1]. So, we will check the previous state dp[i-1][j-arr[i-1]] to see if that sum was possible.
  • Excluding the Element: If we exclude arr[i-1], then the sum remains j, and we will check the previous state dp[i-1][j] to see if that sum was possible without including the element.
C++
#include <bits/stdc++.h>
using namespace std;

// Uses Dynamic Programming to find distinct subset sums
vector<int> distinctSum(vector<int> &arr) {
    int n = arr.size();
    int sum = 0;

    for (int x : arr)
        sum += x;

    vector<vector<bool>> dp(n + 1, vector<bool>(sum + 1));

    // Sum 0 is possible using an empty subset
    for (int i = 0; i <= n; i++)
        dp[i][0] = true;

    // Fill the DP table in bottom-up manner
    for (int i = 1; i <= n; i++) {
        dp[i][arr[i - 1]] = true;

        for (int j = 1; j <= sum; j++) {
            if (dp[i - 1][j]) {
                dp[i][j] = true;
                dp[i][j + arr[i - 1]] = true;
            }
        }
    }

    vector<int> result;

    for (int j = 0; j <= sum; j++) {
        if (dp[n][j])
            result.push_back(j);
    }

    return result;
}

int main() {
    vector<int> arr = {2, 3, 4, 5, 6};

    vector<int> result = distinctSum(arr);

    cout << "[";
    for (int i = 0; i < result.size(); i++) {
        cout << result[i];
        if (i + 1 < result.size())
            cout << ", ";
    }
    cout << "]";

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    // Uses Dynamic Programming to find distinct subset sums
    static ArrayList<Integer> distinctSum(int[] arr) {
        int n = arr.length;
        int sum = 0;

        for (int x : arr)
            sum += x;

        boolean[][] dp = new boolean[n + 1][sum + 1];

        // Sum 0 is possible using an empty subset
        for (int i = 0; i <= n; i++)
            dp[i][0] = true;

        // Fill the DP table in bottom-up manner
        for (int i = 1; i <= n; i++) {
            dp[i][arr[i - 1]] = true;

            for (int j = 1; j <= sum; j++) {
                if (dp[i - 1][j]) {
                    dp[i][j] = true;
                    dp[i][j + arr[i - 1]] = true;
                }
            }
        }

        ArrayList<Integer> result = new ArrayList<>();

        for (int j = 0; j <= sum; j++) {
            if (dp[n][j])
                result.add(j);
        }

        return result;
    }

    static void printList(ArrayList<Integer> result) {
        System.out.print("[");
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i));

            if (i + 1 < result.size())
                System.out.print(", ");
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        int[] arr = {2, 3, 4, 5, 6};

        ArrayList<Integer> result = distinctSum(arr);

        printList(result);
    }
}
Python
# Uses Dynamic Programming to find distinct subset sums
def distinctSum(arr):
    n = len(arr)
    total_sum = sum(arr)

    dp = [[False] * (total_sum + 1) for _ in range(n + 1)]

    # Sum 0 is possible using an empty subset
    for i in range(n + 1):
        dp[i][0] = True

    # Fill the DP table in bottom-up manner
    for i in range(1, n + 1):
        dp[i][arr[i - 1]] = True

        for j in range(1, total_sum + 1):
            if dp[i - 1][j]:
                dp[i][j] = True
                dp[i][j + arr[i - 1]] = True

    result = []

    for j in range(total_sum + 1):
        if dp[n][j]:
            result.append(j)

    return result


if __name__ == "__main__":
    arr = [2, 3, 4, 5, 6]

    result = distinctSum(arr)

    print("[" + ", ".join(map(str, result)) + "]")
C#
using System;
using System.Collections.Generic;

class GFG {

    // Uses Dynamic Programming to find distinct subset sums
    static List<int> distinctSum(List<int> arr) {
        int n = arr.Count;
        int sum = 0;

        foreach (int x in arr)
            sum += x;

        bool[,] dp = new bool[n + 1, sum + 1];

        // Sum 0 is possible using an empty subset
        for (int i = 0; i <= n; i++)
            dp[i, 0] = true;

        // Fill the DP table in bottom-up manner
        for (int i = 1; i <= n; i++) {
            dp[i, arr[i - 1]] = true;

            for (int j = 1; j <= sum; j++) {
                if (dp[i - 1, j]) {
                    dp[i, j] = true;
                    dp[i, j + arr[i - 1]] = true;
                }
            }
        }

        List<int> result = new List<int>();

        for (int j = 0; j <= sum; j++) {
            if (dp[n, j])
                result.Add(j);
        }

        return result;
    }

    static void Main() {
        List<int> arr = new List<int> { 2, 3, 4, 5, 6 };

        List<int> result = distinctSum(arr);

        Console.WriteLine("[" + string.Join(", ", result) + "]");
    }
}
JavaScript
function distinctSum(arr) {
    let n = arr.length;
    let sum = arr.reduce((a, b) => a + b, 0);

    let dp = Array.from(
        { length: n + 1 },
        () => new Uint8Array(sum + 1)
    );

    // Sum 0 is possible using an empty subset
    for (let i = 0; i <= n; i++)
        dp[i][0] = 1;

    // Fill the DP table in bottom-up manner
    for (let i = 1; i <= n; i++) {
        dp[i][arr[i - 1]] = 1;

        for (let j = 1; j <= sum; j++) {
            if (dp[i - 1][j]) {
                dp[i][j] = 1;
                dp[i][j + arr[i - 1]] = 1;
            }
        }
    }

    let result = [];

    for (let j = 0; j <= sum; j++) {
        if (dp[n][j])
            result.push(j);
    }

    return result;
}

// Driver Code
let arr = [2, 3, 4, 5, 6];

let result = distinctSum(arr);

console.log("[" + result.join(", ") + "]");

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

[Expected Approach] Optimized Bit-Set Approach

  • dp = dp | dp << a[i]

Above Code snippet does the same as naive solution, where dp is a bit mask (we’ll use bit-set). Lets see how:

  • dp represents all the sums which were produced before element a[i].
  • dp << a[i] represents shifting all the possible sums by a[i], i.e., adding a[i] to all the sums.
  • dp | (dp << a[i]) gives the union of the old sums and the new sums.

For example, Suppose initially the bit-mask was 000010100 meaning we could generate only 2 and 4 (count from right). Now if we get an element 3, we could make 5 and 7 as well by adding to 2 and 4 respectively. This can be denoted by 010100000 which is equivalent to (000010100) << 3. dp | (dp << a[i]) is 000010100 | 010100000 = 010110100 This is union of above two sums representing which sums are possible, namely 2, 4, 5 and 7.

find-all-distinct-subset-or-subsequence-sums-of-an-array
C++
#include <bits/stdc++.h>
using namespace std;

vector<int> distinctSum(vector<int> &arr) {
    int sum = accumulate(arr.begin(), arr.end(), 0);

    int words = (sum + 64) / 64;
    vector<unsigned long long> dp(words);

    dp[0] = 1ULL;

    for (int num : arr) {
        int shiftWords = num / 64;
        int shiftBits = num % 64;

        vector<unsigned long long> temp = dp;

        // Add the current element to all possible sums
        for (int i = 0; i < words; i++) {
            if (dp[i] == 0)
                continue;

            int j = i + shiftWords;

            if (j < words) {
                temp[j] |= dp[i] << shiftBits;

                if (shiftBits != 0 && j + 1 < words)
                    temp[j + 1] |= dp[i] >> (64 - shiftBits);
            }
        }

        dp = temp;
    }

    vector<int> result;

    // Collect all sums that are possible
    for (int i = 0; i <= sum; i++) {
        int word = i / 64;
        int bit = i % 64;

        if ((dp[word] >> bit) & 1ULL)
            result.push_back(i);
    }

    return result;
}

int main() {
    vector<int> arr = {2, 3, 4, 5, 6};

    vector<int> result = distinctSum(arr);

    cout << "[";
    for (int i = 0; i < result.size(); i++) {
        cout << result[i];

        if (i + 1 < result.size())
            cout << ", ";
    }
    cout << "]";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.BitSet;

class GFG {

    static ArrayList<Integer> distinctSum(int[] arr) {
        int sum = 0;

        for (int x : arr)
            sum += x;

        BitSet dp = new BitSet(sum + 1);
        dp.set(0);

        for (int num : arr) {
            BitSet temp = new BitSet(sum + 1);

            // Add the current element to all possible sums
            for (int j = dp.nextSetBit(0);
                 j >= 0 && j <= sum - num;
                 j = dp.nextSetBit(j + 1)) {
                temp.set(j + num);
            }

            dp.or(temp);
        }

        ArrayList<Integer> result = new ArrayList<>();

        // Collect all sums that are possible
        for (int i = 0; i <= sum; i++) {
            if (dp.get(i))
                result.add(i);
        }

        return result;
    }

    static void printList(ArrayList<Integer> result) {
        System.out.print("[");
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i));

            if (i + 1 < result.size())
                System.out.print(", ");
        }
        System.out.println("]");
    }

    public static void main(String[] args) {
        int[] arr = {2, 3, 4, 5, 6};

        ArrayList<Integer> result = distinctSum(arr);

        printList(result);
    }
}
Python
def distinctSum(arr):
    total_sum = sum(arr)

    dp = 1

    for num in arr:
        # Add the current element to all possible sums
        dp |= dp << num

    result = []

    # Collect all sums that are possible
    for i in range(total_sum + 1):
        if (dp >> i) & 1:
            result.append(i)

    return result


if __name__ == "__main__":
    arr = [2, 3, 4, 5, 6]

    result = distinctSum(arr)

    print("[" + ", ".join(map(str, result)) + "]")
C#
using System;
using System.Collections.Generic;

class GFG {

    static List<int> distinctSum(List<int> arr) {
        int sum = 0;

        foreach (int x in arr)
            sum += x;

        int words = (sum + 64) / 64;
        ulong[] dp = new ulong[words];

        dp[0] = 1UL;

        foreach (int num in arr) {
            ulong[] temp = (ulong[])dp.Clone();

            int wordShift = num / 64;
            int bitShift = num % 64;

            // Add the current element to all possible sums
            for (int i = 0; i < words; i++) {
                if (dp[i] == 0)
                    continue;

                int j = i + wordShift;

                if (j < words) {
                    temp[j] |= dp[i] << bitShift;

                    if (bitShift != 0 && j + 1 < words)
                        temp[j + 1] |= dp[i] >> (64 - bitShift);
                }
            }

            dp = temp;
        }

        List<int> result = new List<int>();

        // Collect all sums that are possible
        for (int i = 0; i <= sum; i++) {
            int word = i / 64;
            int bit = i % 64;

            if ((dp[word] & (1UL << bit)) != 0)
                result.Add(i);
        }

        return result;
    }

    static void Main() {
        List<int> arr = new List<int> { 2, 3, 4, 5, 6 };

        List<int> result = distinctSum(arr);

        Console.WriteLine("[" + string.Join(", ", result) + "]");
    }
}
JavaScript
function distinctSum(arr) {
    let sum = arr.reduce((a, b) => a + b, 0);

    let dp = 1n;

    for (let num of arr) {
        // Add the current element to all possible sums
        dp |= dp << BigInt(num);
    }

    let result = [];

    // Collect all sums that are possible
    for (let i = 0; i <= sum; i++) {
        if ((dp & (1n << BigInt(i))) !== 0n)
            result.push(i);
    }

    return result;
}

// Driver Code
let arr = [2, 3, 4, 5, 6];

let result = distinctSum(arr);

console.log("[" + result.join(", ") + "]");

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

Time Complexity: also seems to be O(n * s). Because if we would have used a array instead of bitset the shifting would have taken linear time O(S). However the shift (and almost all) operation on bitset takes O(s / w) time. Where w is the word size of the system, Usually its 32 bit or 64 bit. Thus the final time complexity becomes O(n * s / w)

Auxiliary Space:O(m),  where m is the maximum value of the input array.

Some Important Points:

  1. The size of bitset must be a constant, this sometimes is a drawback as we might waste some space.
  2. Bitset can be thought of a array where every element takes care of W elements. For example 010110100 is equivalent to {2, 6, 4} in a hypothetical system with word size w = 3.
  3. Bitset optimized knapsack solution reduced the time complexity by a factor of w which sometimes is just enough to get AC.
     
Comment