Length of longest subset consisting of A 0s and B 1s from an array of strings


In this problem, we need to find the longest subset containing at most A 0s and B1s. All we need to do is find all possible subsets using the array elements and find the longest subset containing maximum A 0s and B1.

In this tutorial, first, we will learn the recursive approach to solve the problem. After that, we will optimize the code using the dynamic programming approach.

Problem statement − We have given an array containing N binary strings. Also, we have given A and B integers. We need to make the longest subset using the given binary strings such that it doesn’t contain more than A 0s and B1s.

Sample Examples

Input –  arr = {"101", "0", "101", "0", "1"}, A = 2, B = 1
Output – 3

Explanation

The longest subset is { "0", "0", "1"}, containing 2 0s and 1 1s.

Input –  arr = {"0", "101", "0", "1"}, A = 3, B = 3
Output – 3

Explanation

The longest subset is {"0", "101", "0", "1"}, 3 0s and 3 1s.

Approach 1

In this section, we will learn a naïve approach using recursion. We will construct all possible subsets using array elements and find the longest subset containing the A 0s and B 1s.

Algorithm

  • Step 1 − Define the countZeros() function to count the total number of zeros in the given binary string.

  • Step 1.1 − Initialize the ‘count’ variable with zero.

  • Step 1.2 − Traverse through the string using the for loop.

  • Step 1.3 − If the character at the ith index is ‘0’, increase the value of ‘cnt’ by 1.

  • Step 1.2 − Returnt the value of the ‘cnt’ variable.

  • Step 2 − The getMaxSubsetLen() returns integer values and takes vector arr, int A, int B, and index as parameters.

  • Step 3 − Define the base case inside the function. If the index is equal to the size of the vector, or the value of A and B both is zero, return 0.

  • Step 4 − Now, count the total number of zeros in the string at the index.

  • Step 5 − Subtract the total number of 1s from the string length to find the total number of 1s.

  • Step 6 − Initialize the ‘first’ variable with 0.

  • Step 7 − If the total number of zeros and ones is less than A and B, respectively, include the current binary string. Store 1 + return value from the recursive call of the function. While making the recursive call, subtract zeros and ones from A and B.

  • Step 8 − Exclude the current string and store the resultant value in the ‘second’ variable.

  • Step 9 − Return the maximum value from the first and second.

Example

#include <bits/stdc++.h>
using namespace std;
// function to count the number of 0's in a string
int countZeros(string s){

   // initialize count variable to 0
   int count = 0;
   
   // traverse the string
   for (int i = 0; i < s.size(); i++){
   
      // if the current character is 0, the increment count
      if (s[i] == '0'){
         count++;
      }
   }
   
   // return count
   return count;
}

// recursive function to find the maximum length of a subset of strings according to the given condition.
int getMaxSubsetLen(vector<string> arr, int A, int B, int index){

   // base case
   // if all the strings are traversed, or A + B becomes 0
   if (index == arr.size() || A + B == 0){
      return 0;
   }
   
   // total number of 0's in arr[index] string
   int zero = countZeros(arr[index]);
   
   // total number of 1's in arr[index] string
   int one = arr[index].size() - zero;
   
   // Stores the length of the subset, if arr[i] is included.
   int first = 0;
   
   // if the number of 0's and 1's in arr[index] is less than or equal to A and B, respectively, then include the string
   if (zero <= A && one <= B){
      first = 1 + getMaxSubsetLen(arr, A - zero, B - one, index + 1);
   }
   
   // Stores the length of the subset, if arr[i] is not included.
   int second = getMaxSubsetLen(arr, A, B, index + 1);
   
   // return the maximum of the first and second
   return max(first, second);
}

// Driver Code
int main(){
   vector<string> arr = {"101", "0", "101", "0", "1"};
   int A = 2, B = 1;
   cout << "The maximum length of the subset consisting at most A 0s and B 1s is - " <<getMaxSubsetLen(arr, A, B, 0);
   return 0;
}

Output

The maximum length of the subset consisting at most A 0s and B 1s is - 3

Time complexity − O(2N), as we find all possible subsets using N array elements.

Space complexity − O(1)

Approach 2

We have optimized the above approach in this section. We used the dynamic programming approach to solve the problem. It stores the result of the previous state to decrease the time complexity of the problem.

Algorithm

  • Step 1 − Define the countZeros() function to count a total number of zeros in a particular binary string as we have done in the above approach.

  • Step 2 − Create a 3-dimensional vector of size A x B x N to store the result of the previous state. In the list, we will store the length of the subset at index ‘I’ when total zeros are equal to A and 1s are equal to B. Also, pass it as a parameter of the getMaxSubsetLen() function.

  • Step 3 − Define the base case as we have done in the above approach.

  • Step 4 − If dpTable[A][B][index]’s value is greater than 0, it means the state is already calculated and returns its value.

  • Step 5 − Count the total number of zeros and ones in the current string.

  • Step 6 − Get the resultant value after including and excluding the current string.

  • Step 7 − Use the max() function to get the maximum value from the first and second, and return it after storing at the dpTable[A][B][index]

Example

#include <bits/stdc++.h>
using namespace std;
// function to count the number of 0's in a string
int countZeros(string s){

   // initialize count variable to 0
   int count = 0;
   
   // traverse the string
   for (int i = 0; i < s.size(); i++){
   
      // if the current character is 0, the increment count
      if (s[i] == '0'){
         count++;
      }
   }
   
   // return count
   return count;
}

// recursive function to find the maximum length of a subset of strings according to the given condition.
int getMaxSubsetLen(vector<string> array, int A, int B, int index, vector<vector<vector<int>>> &dpTable){

   // base case
   if (index == array.size() || A + B == 0){
      return 0;
   }
   
   // return if already calculated
   if (dpTable[A][B][index] > 0){
      return dpTable[A][B][index];
   }
   
   // total number of 0's in the current string
   int zero = countZeros(array[index]);
   
   // total number of 1's in the current string
   int one = array[index].size() - zero;
   
   // to store the length of the subset can be formed by including the current string
   int first = 0;
   
   // if the total number of 0's and 1's in the current string is less than or equal to A and B, respectively
   if (zero <= A && one <= B){
      first = 1 + getMaxSubsetLen(array, A - zero, B - one, index + 1, dpTable);
   }
   
   // to store the length of the subset can be formed by excluding the current string
   int second = getMaxSubsetLen(array, A, B, index + 1, dpTable);
   
   // store the maximum of the first and second, and return
   return dpTable[A][B][index] = max(first, second);
}
int main(){
   vector<string> arr = {"101", "0", "101", "0", "1"};
   int A = 2, B = 1;
   vector<vector<vector<int>>> dpTable(A + 1, vector<vector<int>>(B + 1, vector<int>(arr.size() + 1, 0)));
   cout << "The maximum length of the subset consisting at most A 0s and B 1s is - " << getMaxSubsetLen(arr, A, B, 0, dpTable);
   return 0;
}

Output

The maximum length of the subset consisting at most A 0s and B 1s is - 3

Time complexity − O(A*B*N), as we need to fill a 3D list to get a result.

Space complexity − O(A*B*N), as we use the 3D list for a dynamic programming approach.

Updated on: 28-Jul-2023

58 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements