Length of longest subset consisting of A 0s and B 1s from an array of strings
Given an array arr[] consisting of N binary strings, and two integers A and B, the task is to find the length of the longest subset consisting of at most A 0s and B 1s.
Examples:
Input: arr[] = {“1”, “0”, “0001”, “10”, “111001”}, A = 5, B = 3
Output: 4
Explanation:
One possible way is to select the subset {arr[0], arr[1], arr[2], arr[3]}.
Total number of 0s and 1s in all these strings are 5 and 3 respectively.
Also, 4 is the length of the longest subset possible.
Input: arr[] = {“0”, “1”, “10”}, A = 1, B = 1
Output: 2
Explanation:
One possible way is to select the subset {arr[0], arr[1]}.
Total number of 0s and 1s in all these strings is 1 and 1 respectively.
Also, 2 is the length of the longest subset possible.
Naive Approach: The simplest approach to solve the above problem is to use recursion. At every recursive call, the idea is to either include or exclude the current string. Once, all possibilities are considered, print the maximum length of subset obtained.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int count0(string s)
{
int count = 0;
for ( int i = 0; i < s.size(); i++) {
if (s[i] == '0' ) {
count++;
}
}
return count;
}
int solve(vector<string> vec,
int A, int B, int idx)
{
if (idx == vec.size() || A + B == 0) {
return 0;
}
int zero = count0(vec[idx]);
int one = vec[idx].size() - zero;
int inc = 0;
if (zero <= A && one <= B) {
inc = 1 + solve(vec, A - zero,
B - one, idx + 1);
}
int exc = solve(vec, A, B, idx + 1);
return max(inc, exc);
}
int MaxSubsetlength(vector<string> arr,
int A, int B)
{
return solve(arr, A, B, 0);
}
int main()
{
vector<string> arr = { "1" , "0" , "10" };
int A = 1, B = 1;
cout << MaxSubsetlength(arr, A, B);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int count0(String s)
{
int count = 0 ;
for ( int i = 0 ; i < s.length(); i++) {
if (s.charAt(i) == '0' ) {
count++;
}
}
return count;
}
static int solve(String[] vec,
int A, int B, int idx)
{
if (idx == vec.length || A + B == 0 ) {
return 0 ;
}
int zero = count0(vec[idx]);
int one = vec[idx].length() - zero;
int inc = 0 ;
if (zero <= A && one <= B) {
inc = 1 + solve(vec, A - zero,
B - one, idx + 1 );
}
int exc = solve(vec, A, B, idx + 1 );
return Math.max(inc, exc);
}
static int MaxSubsetlength(String[] arr,
int A, int B)
{
return solve(arr, A, B, 0 );
}
public static void main (String[] args) {
String[] arr = { "1" , "0" , "10" };
int A = 1 , B = 1 ;
System.out.print(MaxSubsetlength(arr, A, B));
}
}
|
Python3
def count0(s):
count = 0
for i in range ( len (s)):
if (s[i] = = '0' ):
count + = 1
return count
def solve(vec, A, B, idx):
if (idx = = len (vec) or A + B = = 0 ):
return 0
zero = count0(vec[idx])
one = len (vec[idx]) - zero
inc = 0
if (zero < = A and one < = B):
inc = 1 + solve(vec, A - zero,
B - one, idx + 1 )
exc = solve(vec, A, B, idx + 1 )
return max (inc, exc)
def MaxSubsetlength(arr, A, B):
return solve(arr, A, B, 0 )
if __name__ = = '__main__' :
arr = [ "1" , "0" , "10" ]
A = 1
B = 1
print (MaxSubsetlength(arr, A, B))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int count0( string s)
{
int count = 0;
for ( int i = 0; i < s.Length; i++)
{
if (s[i] == '0' )
{
count++;
}
}
return count;
}
static int solve(List< string > vec, int A, int B,
int idx)
{
if (idx == vec.Count || A + B == 0)
{
return 0;
}
int zero = count0(vec[idx]);
int one = vec[idx].Length - zero;
int inc = 0;
if (zero <= A && one <= B)
{
inc = 1 + solve(vec, A - zero,
B - one, idx + 1);
}
int exc = solve(vec, A, B, idx + 1);
return Math.Max(inc, exc);
}
static int MaxSubsetlength(List< string > arr, int A,
int B)
{
return solve(arr, A, B, 0);
}
public static void Main()
{
List< string > arr = new List< string >{ "1" , "0" , "10" };
int A = 1, B = 1;
Console.WriteLine(MaxSubsetlength(arr, A, B));
}
}
|
Javascript
<script>
function count0(s)
{
let count = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] == '0 ') {
count++;
}
}
return count;
}
// Recursive function to find the length of
// longest subset from an array of strings
// with at most A 0' s and B 1 's
function solve(vec, A, B, idx)
{
// If idx is equal to N
// or A + B is equal to 0
if (idx == vec.length || A + B == 0) {
return 0;
}
// Stores the count of 0' s in arr[idx]
let zero = count0(vec[idx]);
let one = vec[idx].length - zero;
let inc = 0;
if (zero <= A && one <= B) {
inc = 1 + solve(vec, A - zero,
B - one, idx + 1);
}
let exc = solve(vec, A, B, idx + 1);
return Math.max(inc, exc);
}
function MaxSubsetlength(arr, A, B)
{
return solve(arr, A, B, 0);
}
let arr = [ "1" , "0" , "10" ];
let A = 1, B = 1;
document.write(MaxSubsetlength(arr, A, B));
</script>
|
Time Complexity: O(2N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized using Memoization, based on the following observations:
Recursion Tree
- It can be observed that there exists a overlapping subproblem and optimal substructure property.
Therefore, the idea is to use dynamic programming to optimize the above approach.
- The idea is to use the 3D-state dynamic programming.
- Suppose Dp(i, A, B) represents the maximum length of the subset with at most A 0s and B 1s.
- Then the transition of states can be defined by either selecting a string at ith index or not,
- Dp(i, A, B) = Max(1+Dp(i+1, A- Z, B-O), Dp(i+1, A, B)),
where Z is the count of Os and O is the count of 0s.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int count0(string s)
{
int count = 0;
for ( int i = 0; i < s.size(); i++) {
if (s[i] == '0' ) {
count++;
}
}
return count;
}
int solve(vector<string> vec, int A,
int B, int idx,
vector<vector<vector< int > > >& dp)
{
if (idx == vec.size() || A + B == 0) {
return 0;
}
if (dp[A][B][idx] > 0) {
return dp[A][B][idx];
}
int zero = count0(vec[idx]);
int one = vec[idx].size() - zero;
int inc = 0;
if (zero <= A && one <= B) {
inc = 1
+ solve(vec, A - zero,
B - one, idx + 1, dp);
}
int exc = solve(vec, A, B, idx + 1, dp);
dp[A][B][idx] = max(inc, exc);
return dp[A][B][idx];
}
int MaxSubsetlength(vector<string> arr,
int A, int B)
{
vector<vector<vector< int > > > dp(
A + 1,
vector<vector< int > >(B + 1,
vector< int >(arr.size() + 1,
0)));
return solve(arr, A, B, 0, dp);
}
int main()
{
vector<string> arr = { "1" , "0" , "10" };
int A = 1, B = 1;
cout << MaxSubsetlength(arr, A, B);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int count0(String s)
{
int count = 0 ;
for ( int i = 0 ; i < s.length(); i++) {
if (s.charAt(i) == '0' ) {
count++;
}
}
return count;
}
static int solve(String []vec, int A,
int B, int idx,
int dp[][][])
{
if (idx == vec.length || A + B == 0 ) {
return 0 ;
}
if (dp[A][B][idx] > 0 ) {
return dp[A][B][idx];
}
int zero = count0(vec[idx]);
int one = vec[idx].length() - zero;
int inc = 0 ;
if (zero <= A && one <= B) {
inc = 1
+ solve(vec, A - zero,
B - one, idx + 1 , dp);
}
int exc = solve(vec, A, B, idx + 1 , dp);
dp[A][B][idx] = Math.max(inc, exc);
return dp[A][B][idx];
}
static int MaxSubsetlength(String []arr,
int A, int B)
{
int dp[][][] = new int [A+ 1 ][B+ 1 ][arr.length+ 1 ];
return solve(arr, A, B, 0 , dp);
}
public static void main (String[] args) {
String arr[] = { "1" , "0" , "10" };
int A = 1 , B = 1 ;
System.out.println(MaxSubsetlength(arr, A, B));
}
}
|
Python3
def count0(s):
count = 0
for i in range ( len (s)):
if (s[i] = = '0' ):
count + = 1
return count
def solve(vec, A, B, idx, dp):
if (idx = = len (vec) or (A + B) = = 0 ):
return 0
if (dp[A][B][idx] > 0 ):
return dp[A][B][idx]
zero = count0(vec[idx])
one = len (vec[idx]) - zero
inc = 0
if (zero < = A and one < = B):
inc = 1 + solve(vec, A - zero, B - one, idx + 1 , dp)
exc = solve(vec, A, B, idx + 1 , dp)
dp[A][B][idx] = max (inc, exc)
return dp[A][B][idx]
def MaxSubsetlength(arr, A, B):
dp = [[ [ 0 for col in range ( len (arr) + 1 )] for col in range (B + 1 )] for row in range (A + 1 )]
return solve(arr, A, B, 0 , dp)
arr = [ "1" , "0" , "10" ]
A, B = 1 , 1
print (MaxSubsetlength(arr, A, B))
|
C#
using System;
public class GFG{
static int count0( string s)
{
int count = 0;
for ( int i = 0; i < s.Length; i++) {
if (s[i] == '0' ) {
count++;
}
}
return count;
}
static int solve( string []vec, int A,
int B, int idx,
int [,,] dp)
{
if (idx == vec.Length || A + B == 0) {
return 0;
}
if (dp[A,B,idx] > 0) {
return dp[A,B,idx];
}
int zero = count0(vec[idx]);
int one = vec[idx].Length - zero;
int inc = 0;
if (zero <= A && one <= B) {
inc = 1
+ solve(vec, A - zero,
B - one, idx + 1, dp);
}
int exc = solve(vec, A, B, idx + 1, dp);
dp[A,B,idx] = Math.Max(inc, exc);
return dp[A,B,idx];
}
static int MaxSubsetlength( string []arr,
int A, int B)
{
int [,,] dp = new int [A+1,B+1,arr.Length+1];
return solve(arr, A, B, 0, dp);
}
static public void Main ()
{
string [] arr = { "1" , "0" , "10" };
int A = 1, B = 1;
Console.WriteLine(MaxSubsetlength(arr, A, B));
}
}
|
Javascript
<script>
function count0(s)
{
let count = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] == '0' ) {
count++;
}
}
return count;
}
function solve(vec, A, B, idx, dp)
{
if (idx == vec.length || A + B == 0)
{
return 0;
}
if (dp[A][B][idx] > 0) {
return dp[A][B][idx];
}
let zero = count0(vec[idx]);
let one = vec[idx].length - zero;
let inc = 0;
if (zero <= A && one <= B) {
inc = 1
+ solve(vec, A - zero,
B - one, idx + 1, dp);
}
let exc = solve(vec, A, B, idx + 1, dp);
dp[A][B][idx] = Math.max(inc, exc);
return dp[A][B][idx];
}
function MaxSubsetlength(arr, A, B)
{
let dp = new Array(A+1);
for (let i = 0; i < A + 1; i++)
{
dp[i] = new Array(B+1);
for (let j = 0; j < B+1;j++)
{
dp[i][j] = new Array(arr.length+1);
for (let k = 0; k < arr.length + 1; k++)
{
dp[i][j][k] = 0;
}
}
}
return solve(arr, A, B, 0, dp);
}
let arr = [ "1" , "0" , "10" ];
let A = 1, B = 1;
document.write(MaxSubsetlength(arr, A, B));
</script>
|
Time Complexity: O(N*A*B)
Auxiliary Space: O(N*A*B)
Last Updated :
04 Oct, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...