Maximum number of strings that can be formed with given zeros and ones
Given a list of strings arr[] of zeros and ones only and two integer N and M, where N is the number of 1’s and M is the number of 0’s. The task is to find the maximum number of strings from the given list of strings that can be constructed with given number of 0’s and 1’s.
Examples:
Input: arr[] = {“10”, “0001”, “11100”, “1”, “0”}, M = 5, N = 3
Output: 4
Explanation:
The 4 strings which can be formed using five 0’s and three 1’s are: “10”, “0001”, “1”, “0”
Input: arr[] = {“10”, “00”, “000”, “0001”, “111001”, “1”, “0”}, M = 3, N = 1
Output: 3
Explanation:
The 3 strings which can be formed using three 0’s and one 1’s are: “00”, “1”, “0”
Naive Approach: The idea is to generate all the combinations of the given list of strings and check the count of zeros and ones satisfying the given condition. But the time complexity of this solution is exponential.
Intuition:
The first thing that we will see is that
- From the given array of strings, we have to choose some of its indices, such that after choosing them we will count our ones and zeros.
- So, this is a kind of option type thing, suppose we start traversing in our given vector and stand on any ith index, then for that index we have a choice.
- And what choice is that? The choice is that we will ask ourselves whether to include this string in our answer or not.
- So, if we decide to choose this string in our answer then we will add the count of ones and zeroes of this string in our answer and move ahead and if we decide not to include this string in our answer, then we will do nothing, we just move forward.
- So, Overall we can say that we have a choice for every index of array whether to include our answer or not to include.
- And whenever we heard a term that here we have a choice like this, then we will say recursion will use here.
- Why recursion? Recursion is because it will try out every single possibility for every string in our answer.
C++
#include <bits/stdc++.h>
using namespace std;
pair< int , int > countOneAndZero(string s)
{
int one = 0, zero = 0;
for ( int i = 0; i < s.length(); i++)
{
if (s[i] == '1' )
one++;
else
zero++;
}
return {one, zero};
}
int countString( int i, int one, int zero, int & maxZero, int & maxOne,
vector<string>& arr)
{
if (i >= arr.size())
return 0;
if (one > maxOne || zero > maxZero)
return 0;
pair< int , int > p = countOneAndZero(arr[i]);
int ans1 = 0, ans2 = 0, ansWithout = 0;
if (one + p.first <= maxOne && zero + p.second <= maxZero)
{
ans1 = 1 + countString(i + 1, one + p.first, zero + p.second,
maxZero, maxOne, arr);
ans2 = countString(i + 1, one, zero, maxZero, maxOne, arr);
}
else
{
ansWithout = countString(i + 1, one, zero, maxZero, maxOne, arr);
}
return max({ans1, ans2, ansWithout});
}
int main() {
vector<string> arr = { "10" , "0001" , "1" ,
"111001" , "0" };
int N = 3, M = 5;
int idx=0;
int one=0;
int zero=0;
cout << countString(idx,one,zero,M, N, arr);
}
|
Java
import java.util.*;
public class GFG {
static class pair {
int first, second;
pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static pair countOneAndZero(String s)
{
int one = 0 , zero = 0 ;
for ( int i = 0 ; i < s.length();
i++)
{
if (s.charAt(i)
== '1' )
one++;
else
zero++;
}
return new pair(one, zero);
}
static int countString( int i, int one, int zero,
int maxZero, int maxOne,
String[] arr)
{
if (i >= arr.length)
return 0 ;
if (one > maxOne || zero > maxZero)
return 0 ;
pair p = countOneAndZero(arr[i]);
int ans1 = 0 , ans2 = 0 , ansWithout = 0 ;
if (one + p.first <= maxOne
&& zero + p.second <= maxZero) {
ans1 = 1
+ countString(i + 1 , one + p.first,
zero + p.second, maxZero,
maxOne, arr);
ans2 = countString(i + 1 , one, zero, maxZero,
maxOne, arr);
}
else
{
ansWithout = countString(i + 1 , one, zero,
maxZero, maxOne, arr);
}
return Math.max(ans1, Math.max(ans2, ansWithout));
}
public static void main(String[] args)
{
String[] arr = { "10" , "0001" , "1" , "111001" , "0" };
int N = 3 , M = 5 ;
int idx = 0 ;
int one = 0 ;
int zero = 0 ;
System.out.println(
countString(idx, one, zero, M, N, arr));
}
}
|
Python3
def countOneAndZero(s):
one, zero = 0 , 0
for i in range ( len (s)):
if (s[i] = = '1' ):
one + = 1
else :
zero + = 1
return [one, zero]
def countString(i, one, zero, maxZero, maxOne, arr):
if (i > = len (arr)):
return 0
if (one > maxOne or zero > maxZero):
return 0
p = countOneAndZero(arr[i])
ans1, ans2, ansWithout = 0 , 0 , 0
if (one + p[ 0 ] < = maxOne and zero + p[ 1 ] < = maxZero):
ans1 = 1 + countString(i + 1 , one +
p[ 0 ], zero + p[ 1 ], maxZero, maxOne, arr)
ans2 = countString(i + 1 , one, zero, maxZero, maxOne, arr)
else :
ansWithout = countString(i + 1 , one, zero, maxZero, maxOne, arr)
return max (ans1, max (ans2, ansWithout))
arr = [ "10" , "0001" , "1" , "111001" , "0" ]
N, M = 3 , 5
idx, one, zero = 0 , 0 , 0
print (countString(idx, one, zero, M, N, arr))
|
C#
using System;
class GFG
{
static int [] countOneAndZero(String s)
{
int one = 0, zero = 0;
for ( int i = 0; i < s.Length;
i++)
{
if (s[i] == '1' )
one++;
else
zero++;
}
int [] p = { one, zero };
return p;
}
static int countString( int i, int one, int zero,
int maxZero, int maxOne,
String[] arr)
{
if (i >= arr.Length)
return 0;
if (one > maxOne || zero > maxZero)
return 0;
int [] p = countOneAndZero(arr[i]);
int ans1 = 0, ans2 = 0, ansWithout = 0;
if (one + p[0] <= maxOne
&& zero + p[1] <= maxZero) {
ans1 = 1
+ countString(i + 1, one + p[0],
zero + p[1], maxZero,
maxOne, arr);
ans2 = countString(i + 1, one, zero, maxZero,
maxOne, arr);
}
else
{
ansWithout = countString(i + 1, one, zero,
maxZero, maxOne, arr);
}
return Math.Max(ans1, Math.Max(ans2, ansWithout));
}
static void Main()
{
String[] arr = { "10" , "0001" , "1" , "111001" , "0" };
int N = 3, M = 5;
int idx = 0;
int one = 0;
int zero = 0;
Console.Write(
countString(idx, one, zero, M, N, arr));
}
}
|
Javascript
function countOneAndZero(s)
{
let one = 0, zero = 0;
for (let i = 0; i < s.length; i++)
{
if (s[i] == '1' )
one++;
else
zero++;
}
let a=[];
a.push(one);
a.push(zero);
return a;
}
function countString(i, one, zero, maxZero, maxOne, arr)
{
if (i >= arr.length)
return 0;
if (one > maxOne || zero > maxZero)
return 0;
let p = countOneAndZero(arr[i]);
let ans1 = 0, ans2 = 0, ansWithout = 0;
if (one + p[0] <= maxOne && zero + p[1] <= maxZero)
{
ans1 = 1 + countString(i + 1, one + p[0], zero + p[1],
maxZero, maxOne, arr);
ans2 = countString(i + 1, one, zero, maxZero, maxOne, arr);
}
else
{
ansWithout = countString(i + 1, one, zero, maxZero, maxOne, arr);
}
return Math.max(ansWithout,Math.max(ans1,ans2));
}
let arr = [ "10" , "0001" , "1" ,
"111001" , "0" ];
let N = 3, M = 5;
let idx = 0;
let one = 0;
let zero = 0;
console.log(countString(idx,one,zero,M, N, arr));
|
Time Complexity: O(2N), where N is the number of strings in the list.
Efficient Approach:
An efficient solution is given by using Dynamic Programming. The idea is to use recursion for generating all possible combinations and store the results for Overlapping Subproblems during recursion.
Below are the steps:
- The idea is to use 3D dp array(dp[M][N][i]) where N and M are the number of 1’s and 0’s respectively and i is the index of the string in the list.
- Find the number of 1’s and 0’s in the current string and check if the count of the zeros and ones is less than or equals to the given count N and M respectively.
- If above condition is true, then check whether current state value is stored in the dp table or not. If yes then return this value.
- Else recursively move for the next iteration by including and excluding the current string as:
// By including the current string
x = 1 + recursive_function(M - zero, N - ones, arr, i + 1)
// By excluding the current string
y = recursive_function(M, N, arr, i + 1)
// and update the dp table as:
dp[M][N][i] = max(x, y)
- The maximum value of the above two recursive calls will give the maximum number with N 1’s and M 0’s for the current state.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[100][100][100];
int countString( int m, int n,
vector<string>& arr, int i)
{
if (m < 0 || n < 0) {
return INT_MIN;
}
if (i >= arr.size()) {
return 0;
}
if (dp[m][n][i] != -1) {
return dp[m][n][i];
}
int zero = 0, one = 0;
for ( char c : arr[i]) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = 1 + countString(m - zero,
n - one,
arr, i + 1);
int y = countString(m, n, arr, i + 1);
return dp[m][n][i] = max(x, y);
}
int main()
{
vector<string> arr = { "10" , "0001" , "1" ,
"111001" , "0" };
int N = 3, M = 5;
memset (dp, -1, sizeof (dp));
cout << countString(M, N, arr, 0);
}
|
Java
class GFG{
static int [][][]dp = new int [ 100 ][ 100 ][ 100 ];
static int countString( int m, int n,
String []arr, int i)
{
if (m < 0 || n < 0 ) {
return Integer.MIN_VALUE;
}
if (i >= arr.length) {
return 0 ;
}
if (dp[m][n][i] != - 1 ) {
return dp[m][n][i];
}
int zero = 0 , one = 0 ;
for ( char c : arr[i].toCharArray()) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = 1 + countString(m - zero,
n - one,
arr, i + 1 );
int y = countString(m, n, arr, i + 1 );
return dp[m][n][i] = Math.max(x, y);
}
public static void main(String[] args)
{
String []arr = { "10" , "0001" , "1" ,
"111001" , "0" };
int N = 3 , M = 5 ;
for ( int i = 0 ;i< 100 ;i++){
for ( int j = 0 ;j< 100 ;j++){
for ( int l= 0 ;l< 100 ;l++)
dp[i][j][l]=- 1 ;
}
}
System.out.print(countString(M, N, arr, 0 ));
}
}
|
Python3
import sys
dp = [[[ - 1 for i in range ( 100 )] for j in range ( 100 )] for k in range ( 100 )]
def countString(m, n, arr, i):
if (m < 0 or n < 0 ):
return - sys.maxsize - 1
if (i > = len (arr)):
return 0
if (dp[m][n][i] ! = - 1 ):
return dp[m][n][i]
zero = 0
one = 0
for c in arr[i]:
if (c = = '0' ):
zero + = 1
else :
one + = 1
x = 1 + countString(m - zero, n - one, arr, i + 1 )
y = countString(m, n, arr, i + 1 )
dp[m][n][i] = max (x, y)
return dp[m][n][i]
if __name__ = = '__main__' :
arr = [ "10" , "0001" , "1" , "111001" , "0" ]
N = 3
M = 5
print (countString(M, N, arr, 0 ))
|
C#
using System;
class GFG{
static int [,,]dp = new int [100, 100, 100];
static int countString( int m, int n,
String []arr, int i)
{
if (m < 0 || n < 0) {
return int .MinValue;
}
if (i >= arr.Length) {
return 0;
}
if (dp[m, n, i] != -1) {
return dp[m, n, i];
}
int zero = 0, one = 0;
foreach ( char c in arr[i].ToCharArray()) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = 1 + countString(m - zero,
n - one,
arr, i + 1);
int y = countString(m, n, arr, i + 1);
return dp[m, n, i] = Math.Max(x, y);
}
public static void Main(String[] args)
{
String []arr = { "10" , "0001" , "1" ,
"111001" , "0" };
int N = 3, M = 5;
for ( int i = 0; i < 100; i++){
for ( int j = 0; j < 100; j++){
for ( int l = 0; l < 100; l++)
dp[i, j, l] = -1;
}
}
Console.Write(countString(M, N, arr, 0));
}
}
|
Javascript
<script>
let dp = new Array();
for (let i = 0; i < 100; i++)
{
dp[i] = new Array();
for (let j = 0; j < 100; j++)
{
dp[i][j] = new Array();
for (let l = 0; l < 100; l++)
{
dp[i][j][l] = -1;
}
}
}
function countString(m, n, arr, i)
{
if (m < 0 || n < 0)
{
return Number.MIN_VALUE;
}
if (i >= arr.length)
{
return 0;
}
if (dp[m][n][i] != -1)
{
return dp[m][n][i];
}
let zero = 0, one = 0;
for (let c = 0; c < arr[i].length; c++)
{
if (arr[i] == '0' )
{
zero++;
}
else
{
one++;
}
}
let x = 1 + countString(m - zero,
n - one,
arr, i + 1);
let y = countString(m, n, arr, i + 1);
return dp[m][n][i] = Math.max(x, y);
}
let arr = [ "10" , "0001" , "1" , "111001" , "0" ];
let N = 3, M = 5;
document.write(countString(M, N, arr, 0));
</script>
|
Time Complexity: O(N*M*len), where N and M are the numbers of 1’s and 0’s respectively and len is the length of the list.
Auxiliary Space: O(N*M*len)
Efficient approach : DP tabulation (iterative)
The approach to solve this problem is same but DP tabulation(bottom-up) method is better than Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls. In this approach we use 3D DP store computation of subproblems and find the final result using iteration and not with the help of recursion.
Implementation Steps:
- Create a 3D DP table of size (N+1) * (m+1) * (n+1), where N is the number of strings in the given array, m is the maximum count of 0’s and n is the maximum count of 1’s.
- Initialize the DP table with 0 and also set the base cases.
- Iterate through all the states (i, j, k), where i represents the current string, j represents the count of 0’s and k represents the count of 1’s.
- Include the current string and find the number of combinations for the next iteration by checking if the current count of 0’s and 1’s is less than or equal to the maximum counts of 0’s and 1’s respectively, and adding 1 to the value of dp[i+1][j-zero][k-one].
- Exclude the current string and find the number of combinations for the next iteration by taking the value of dp[i+1][j][k].
- Update the maximum of the above two states to the current DP state dp[i][j][k].
- Return the final DP state dp[0][m][n].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int countString( int m, int n, vector<string>& arr)
{
int N = arr.size();
int dp[N + 1][m + 1][n + 1];
memset (dp, 0, sizeof (dp));
for ( int i = 0; i <= m; i++)
for ( int j = 0; j <= n; j++)
dp[N][i][j] = 0;
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 0; j <= m; j++) {
for ( int k = 0; k <= n; k++) {
int zero = 0, one = 0;
for ( char c : arr[i]) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = (j - zero < 0 || k - one < 0)
? INT_MIN
: (1
+ dp[i + 1][j - zero]
[k - one]);
int y = dp[i + 1][j][k];
dp[i][j][k] = max(x, y);
}
}
}
return dp[0][m][n];
}
int main()
{
vector<string> arr
= { "10" , "0001" , "1" , "111001" , "0" };
int N = 3, M = 5;
cout << countString(M, N, arr);
}
|
Java
import java.util.*;
public class Main {
public static int countString( int m, int n,
List<String> arr)
{
int N = arr.size();
int [][][] dp = new int [N + 1 ][m + 1 ][n + 1 ];
for ( int [][] row : dp) {
for ( int [] col : row) {
Arrays.fill(col, 0 );
}
}
for ( int i = 0 ; i <= m; i++) {
for ( int j = 0 ; j <= n; j++) {
dp[N][i][j] = 0 ;
}
}
for ( int i = N - 1 ; i >= 0 ; i--) {
for ( int j = 0 ; j <= m; j++) {
for ( int k = 0 ; k <= n; k++) {
int zero = 0 , one = 0 ;
for ( char c :
arr.get(i).toCharArray()) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = (j - zero < 0 || k - one < 0 )
? Integer.MIN_VALUE
: ( 1
+ dp[i + 1 ][j - zero]
[k - one]);
int y = dp[i + 1 ][j][k];
dp[i][j][k] = Math.max(x, y);
}
}
}
return dp[ 0 ][m][n];
}
public static void main(String[] args)
{
List<String> arr = new ArrayList<>();
arr.add( "10" );
arr.add( "0001" );
arr.add( "1" );
arr.add( "111001" );
arr.add( "0" );
int N = 3 , M = 5 ;
System.out.println(countString(M, N, arr));
}
}
|
Python3
def countString(m, n, arr):
N = len (arr)
dp = [[[ 0 for _ in range (n + 1 )] for _ in range (m + 1 )] for _ in range (N + 1 )]
for i in range (m + 1 ):
for j in range (n + 1 ):
dp[N][i][j] = 0
for i in range (N - 1 , - 1 , - 1 ):
for j in range (m + 1 ):
for k in range (n + 1 ):
zero, one = 0 , 0
for c in arr[i]:
if c = = '0' :
zero + = 1
else :
one + = 1
x = 1 + dp[i + 1 ][j - zero][k - one] if j - zero > = 0 and k - one > = 0 else float ( '-inf' )
y = dp[i + 1 ][j][k]
dp[i][j][k] = max (x, y)
return dp[ 0 ][m][n]
arr = [ "10" , "0001" , "1" , "111001" , "0" ]
N, M = 3 , 5
print (countString(M, N, arr))
|
C#
using System;
using System.Collections.Generic;
class Program {
static int CountStrings( int m, int n, List< string > arr) {
int N = arr.Count;
int [,,] dp = new int [N + 1, m + 1, n + 1];
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= m; j++) {
for ( int k = 0; k <= n; k++) {
dp[i, j, k] = 0;
}
}
}
for ( int i = 0; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
dp[N, i, j] = 0;
}
}
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 0; j <= m; j++) {
for ( int k = 0; k <= n; k++) {
int zero = 0, one = 0;
foreach ( char c in arr[i]) {
if (c == '0' ) {
zero++;
}
else {
one++;
}
}
int x = (j - zero < 0 || k - one < 0) ? int .MinValue : (1 + dp[i + 1, j - zero, k - one]);
int y = dp[i + 1, j, k];
dp[i, j, k] = Math.Max(x, y);
}
}
}
return dp[0, m, n];
}
static void Main( string [] args) {
List< string > arr = new List< string > { "10" , "0001" , "1" , "111001" , "0" };
int N = 3, M = 5;
Console.WriteLine(CountStrings(M, N, arr));
}
}
|
Javascript
function countString(m, n, arr) {
const N = arr.length;
const dp = new Array(N + 1).fill( null ).map(() =>
new Array(m + 1).fill( null ).map(() =>
new Array(n + 1).fill( null )));
for (let i = 0; i <= N; i++) {
for (let j = 0; j <= m; j++) {
for (let k = 0; k <= n; k++) {
dp[i][j][k] = 0;
}
}
}
for (let i = 0; i <= m; i++) {
for (let j = 0; j <= n; j++) {
dp[N][i][j] = 0;
}
}
for (let i = N - 1; i >= 0; i--) {
for (let j = 0; j <= m; j++) {
for (let k = 0; k <= n; k++) {
let zero = 0, one = 0;
for (let c of arr[i]) {
if (c === '0' ) {
zero++;
} else {
one++;
}
}
let x = (j - zero < 0 || k - one < 0)
? Number.MIN_SAFE_INTEGER
: (1 + dp[i + 1][j - zero][k - one]);
let y = dp[i + 1][j][k];
dp[i][j][k] = Math.max(x, y);
}
}
}
return dp[0][m][n];
}
const arr = [ "10" , "0001" , "1" , "111001" , "0" ];
const N = 3, M = 5;
console.log(countString(M, N, arr));
|
Time Complexity: O(N*M*len)
Auxiliary Space: O(N*M*len)
Last Updated :
27 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...