# Largest subset of Array having sum at least 0

Given an array arr[] that contains N integers, the task is to find the largest subset having sum at least 0.

Examples:

Input: arr[] = {5, -7, 0, -5, -3, -1}
Output: 4
Explanation: The largest subset that can be selected is {5, 0, -3, -1}. It has size 4

Input: arr[] = {1, -4, -2, -3}
Output: 1

Naive Approach: The basic idea to solve the problem is by using Recursion based on the following idea:

At every index, there are two choices, either select that element or not. If sum is becoming negative then don’t pick it otherwise pick it. And from every recursion return the size of the largest possible subset between the two choices.

• Use a recursive function and for each index there are two choices either select that element or not.
• Avoid selecting that element, whose value make the sum negative.
• Return the count of maximum picked elements out of both choices.
• The maximum among all of these is the required subset size.

Below is the implementation of the above approach:

## C++

 ` ` `#include ` `using` `namespace` `std;` ` ` `int` `pick_max_elements(``int` `pos, ``int` `sum,` `                      ``int` `n, ``int` `arr[])` `{` ` ` `    ` `    ` `    ``if` `(pos == n)` `        ``return` `0;` ` ` `    ``int` `taken = INT_MIN;` ` ` `    ` `    ``if` `(sum + arr[pos] >= 0)` `        ``taken = 1` `                ``+ pick_max_elements(pos + 1,` `                                    ``sum + arr[pos],` `                                    ``n, arr);` ` ` `    ``int` `not_taken` `        ``= pick_max_elements(pos + 1,` `                            ``sum, n, arr);` ` ` `    ` `    ``return` `max(taken, not_taken);` `}` ` ` `int` `main()` `{` `    ``int` `arr[] = { 1, -4, -2, -3 };` `    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` ` ` `    ` `    ` `    ``cout << pick_max_elements(0, 0, N, arr);` `    ``return` `0;` `}`

Time Complexity: O( 2N)
Auxiliary Space: O(N)

Efficient Approach: The efficient approach is using multiset based on the following idea:

Traverse from start of array and if at any index the sum till now becomes negative then erase the minimum element till current index from the subset. This will increase the subset sum.
To efficacy find the minimum multiset is used.

Follow the illustration given below for a better understanding.

Illustration:

Consider the array arr[] = {1, -4, -2, -3}

multiset s,

-> Insert arr in s. s = {1}. sum = sum + arr = 1

-> Insert arr in s. s = { -4, 1 }. sum = sum + arr = -3
-> Remove the smallest element (ie -4). sum = -3 – (-4) = 1.

-> Insert arr in s. s = { -2, 1 }. sum = sum + arr = -1
-> Remove the smallest element (ie -2). sum = -1 – (-2) = 1.

-> Insert arr in s. s = { -3, 1 }. sum = sum + arr = -2
-> Remove the smallest element (ie is -3). sum = -2 – (-3) = 1.

Total 1 element in the subset

Follow the below steps to solve this problem:

• Iterate from i = 0 to N
• Increment the count
• Add the current element to the subset sum.
• Insert arr[i] into the set.
• If sum becomes negative then subtract the smallest value from the set and also remove the smallest element from the set
• Decrement the count
• Return the final count.

Below is the implementation of the above approach:

## C++

 ` ` `#include ` `using` `namespace` `std;` ` ` `int` `pick_max_elements(``int` `arr[], ``int` `n)` `{` `    ``int` `cnt = 0, sum = 0;` ` ` `    ` `    ``multiset<``int``> s;` ` ` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``sum += arr[i];` ` ` `        ` `        ` `        ``cnt++;` `        ``s.insert(arr[i]);` `        ``if` `(sum < 0) {` `            ``sum = sum - *s.begin();` ` ` `            ` `            ` `            ``s.erase(s.begin());` ` ` `            ` `            ` `            ``cnt--;` `        ``}` `    ``}` `    ``return` `cnt;` `}` ` ` `int` `main()` `{` `    ``int` `arr[] = { 1, -4, -2, -3 };` ` ` `    ` `    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` ` ` `    ` `    ` `    ``cout << pick_max_elements(arr, N);` `    ``return` `0;` `}`

Time complexity: O( N * log N )
Auxiliary Space: O(N )