Largest subset of Array having sum at least 0
Last Updated :
02 Feb, 2023
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.
Follow the steps mentioned below:
- 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 <bits/stdc++.h>
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[0]);
cout << pick_max_elements(0, 0, N, arr);
return 0;
}
|
Java
import java.util.*;
class GFG
{
public static int pick_max_elements( int pos, int sum,
int n, int arr[])
{
if (pos == n)
return 0 ;
int taken = Integer.MIN_VALUE;
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 Math.max(taken, not_taken);
}
public static void main(String[] args)
{
int arr[] = { 1 , - 4 , - 2 , - 3 };
int N = arr.length;
System.out.print(pick_max_elements( 0 , 0 , N, arr));
}
}
|
Python
INT_MIN = - ( 1e9 + 7 )
def pick_max_elements(pos, sum , n, arr):
if (pos = = n):
return 0
taken = INT_MIN
if ( sum + arr[pos] > = 0 ):
taken = 1 + pick_max_elements(pos + 1 , sum + arr[pos], n, arr)
not_taken = pick_max_elements(pos + 1 , sum , n, arr)
return max (taken, not_taken)
arr = [ 1 , - 4 , - 2 , - 3 ]
N = len (arr)
print (pick_max_elements( 0 , 0 , N, arr))
|
C#
using System;
class GFG {
public static int pick_max_elements( int pos, int sum,
int n, int [] arr)
{
if (pos == n)
return 0;
int taken = Int32.MinValue;
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 Math.Max(taken, not_taken);
}
public static void Main( string [] args)
{
int [] arr = { 1, -4, -2, -3 };
int N = arr.Length;
Console.Write(pick_max_elements(0, 0, N, arr));
}
}
|
Javascript
<script>
function pick_max_elements(pos, sum,
n, arr) {
if (pos == n)
return 0;
let taken = Number.MIN_VALUE;
if (sum + arr[pos] >= 0)
taken = 1
+ pick_max_elements(pos + 1,
sum + arr[pos],
n, arr);
let not_taken
= pick_max_elements(pos + 1,
sum, n, arr);
return Math.max(taken, not_taken);
}
let arr = [1, -4, -2, -3];
let N = arr.length;
document.write(pick_max_elements(0, 0, N, arr));
</script>
|
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 efficiently 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 <int> s,
-> Insert arr[0] in s. s = {1}. sum = sum + arr[0] = 1
-> Insert arr[1] in s. s = { -4, 1 }. sum = sum + arr[1] = -3
-> Remove the smallest element (i.e. -4). sum = -3 – (-4) = 1.
-> Insert arr[2] in s. s = { -2, 1 }. sum = sum + arr[2] = -1
-> Remove the smallest element (i.e. -2). sum = -1 – (-2) = 1.
-> Insert arr[3] in s. s = { -3, 1 }. sum = sum + arr[1] = -2
-> Remove the smallest element (i.e. 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 <bits/stdc++.h>
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[0]);
cout << pick_max_elements(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int pick_max_elements( int arr[], int n)
{
int cnt = 0 , sum = 0 ;
Vector<Integer> s = new Vector<>();
for ( int i = 0 ; i < n; i++) {
sum += arr[i];
cnt++;
s.add(arr[i]);
if (sum < 0 ) {
sum = sum - s.get( 0 );
s.remove( 0 );
cnt--;
}
}
return cnt;
}
public static void main(String[] args)
{
int arr[] = { 1 , - 4 , - 2 , - 3 };
int N = arr.length;
System.out.print(pick_max_elements(arr, N));
}
}
|
Python3
import bisect
def pick_max_elements(arr, n) :
cnt = 0
sum = 0
s = []
for i in range ( 0 ,n) :
sum + = arr[i]
cnt + = 1
bisect.insort(s, arr[i])
if sum < 0 :
sum = sum - s[ 0 ]
s.pop( 0 )
cnt - = 1
return cnt
if __name__ = = "__main__" :
arr = [ 1 , - 4 , - 2 , - 3 ]
N = len (arr)
print (pick_max_elements(arr, N))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
public static int pick_max_elements( int [] arr, int n)
{
var cnt = 0;
var sum = 0;
var s = new List< int >();
for ( int i = 0; i < n; i++)
{
sum += arr[i];
cnt++;
s.Add(arr[i]);
if (sum < 0)
{
sum = sum - s[0];
s.RemoveAt(0);
cnt--;
}
}
return cnt;
}
public static void Main(String[] args)
{
int [] arr = {1, -4, -2, -3};
var N = arr.Length;
Console.Write(GFG.pick_max_elements(arr, N));
}
}
|
Javascript
const pickMaxElements = (arr) => {
let cnt = 0, sum = 0;
const s = new Set();
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
cnt++;
s.add(arr[i]);
if (sum < 0) {
sum = sum - Math.min(...s);
s. delete (Math.min(...s));
cnt--;
}
}
return cnt;
}
const arr = [1, -4, -2, -3];
console.log(pickMaxElements(arr));
|
Time complexity: O( N * log N )
Auxiliary Space: O(N )
Share your thoughts in the comments
Please Login to comment...