Given an array arr[] consisting of 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.
Table of Content
Using Recursion – O(2^n) Time and O(n) Space
A simple approach is to consider all the possible subsets of strings and calculating the total counts of zeros and ones in each subset. Consider the only subsets that contain exactly a zeros and b ones. From all such subsets, pick the subset with maximum length.
Case 1: Exclude the current string
- findMaxSubset(index, a, b) = findMaxSubset(index + 1, a, b)
Case 2: Include the current string: Include the current string in the subset if its count of zeros and ones is within the remaining limits (a and b)
- findMaxSubset(index, a, b) = 1 + findMaxSubset(index + 1, a- zeroCount, b - oneCount), where zeroCount and oneCount is the count of zeros and ones of current string.
// C++ program to find the length of the longest subset
// using recursion
#include <iostream>
#include <vector>
using namespace std;
int findMaxSubsetSize(int index, int n, vector<int>
&zeroCounts, vector<string> &strs, int maxZeros, int maxOnes) {
// Base case: if we've processed all strings, return 0
if (index >= n)
return 0;
// Option 1: Skip the current string
int maxSubset = findMaxSubsetSize(index + 1,
n, zeroCounts, strs, maxZeros, maxOnes);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].size() - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent =
1 + findMaxSubsetSize(index + 1, n, zeroCounts,
strs, maxZeros - zeroCount, maxOnes - oneCount);
maxSubset = max(maxSubset, includeCurrent);
}
return maxSubset;
}
int maxSubsetSize(vector<string> &strs, int maxZeros,
int maxOnes) {
int n = strs.size();
// Precompute the count of zeros
// in each string and store in zeroCounts array
vector<int> zeroCounts(n, 0);
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs[i]) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
return findMaxSubsetSize(0, n, zeroCounts, strs,
maxZeros, maxOnes);
}
int main() {
vector<string> arr = {"1", "0", "0001", "10", "111001"};
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
cout << res;
return 0;
}
// Java program to find the length of the longest subset
// using recursion
import java.util.*;
class GfG {
static int findMaxSubsetSize(int index, int n,
int[] zeroCounts,
String[] strs, int maxZeros,
int maxOnes) {
// Base case: if we've processed all strings, return
// 0
if (index >= n)
return 0;
// Option 1: Skip the current string
int maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].length() - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs,
maxZeros - zeroCount,
maxOnes - oneCount);
maxSubset = Math.max(maxSubset, includeCurrent);
}
return maxSubset;
}
static int maxSubsetSize(String[] strs, int maxZeros,
int maxOnes) {
int n = strs.length;
// Precompute the count of zeros in each string and
// store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs[i].toCharArray()) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Start the recursive helper function from the
// first string
return findMaxSubsetSize(0, n, zeroCounts, strs,
maxZeros, maxOnes);
}
public static void main(String[] args) {
String[] arr = { "1", "0", "0001", "10", "111001" };
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
System.out.println(res);
}
}
# Python program to find the length of the longest subset
# using recursion
from typing import List
def findMaxSubsetSize(index: int, n: int, zeroCounts: List[int],\
strs: List[str], maxZeros: int, maxOnes: int) -> int:
# Base case: if we've processed all strings, return 0
if index >= n:
return 0
# Option 1: Skip the current string
maxSubset = findMaxSubsetSize(index + 1, n, \
zeroCounts, strs, maxZeros, maxOnes)
zeroCount = zeroCounts[index]
oneCount = len(strs[index]) - zeroCount
# Option 2: Include the current string if it doesn't
# exceed the max zeros and ones allowed
if zeroCount <= maxZeros and oneCount <= maxOnes:
includeCurrent = 1 + findMaxSubsetSize(index + 1, n, \
zeroCounts, strs, maxZeros - zeroCount, maxOnes - oneCount)
maxSubset = max(maxSubset, includeCurrent)
return maxSubset
def maxSubsetSize(strs: List[str], maxZeros: int, maxOnes: int) -> int:
n = len(strs)
# Precompute the count of zeros in each
# string and store in zeroCounts array
zeroCounts = [s.count('0') for s in strs]
# Start the recursive helper function
# from the first string
return findMaxSubsetSize(0, n, zeroCounts, strs, maxZeros, maxOnes)
arr = ["1", "0", "0001", "10", "111001"]
a, b = 5, 3
res = maxSubsetSize(arr, a, b)
print(res)
// C# program to find the length of the longest subset
// using recursion
using System;
class GfG {
static int findMaxSubsetSize(int index, int n,
int[] zeroCounts,
string[] strs, int maxZeros,
int maxOnes) {
// Base case: if we've processed all strings, return
// 0
if (index >= n)
return 0;
// Option 1: Skip the current string
int maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].Length - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs,
maxZeros - zeroCount,
maxOnes - oneCount);
maxSubset = Math.Max(maxSubset, includeCurrent);
}
return maxSubset;
}
static int maxSubsetSize(string[] strs, int maxZeros,
int maxOnes) {
int n = strs.Length;
// Precompute the count of zeros in each string and
// store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
int countZeros = 0;
foreach(char c in strs[i]) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Start the recursive helper function from the
// first string
return findMaxSubsetSize(0, n, zeroCounts, strs,
maxZeros, maxOnes);
}
static void Main() {
string[] arr = { "1", "0", "0001", "10", "111001" };
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
Console.WriteLine(res);
}
}
// JavaScript program to find the length of the longest
// subset using recursion
function findMaxSubsetSize(index, n, zeroCounts, strs, maxZeros,
maxOnes) {
// Base case: if we've processed all strings, return 0
if (index >= n) {
return 0;
}
// Option 1: Skip the current string
let maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes);
let zeroCount = zeroCounts[index];
let oneCount = strs[index].length - zeroCount;
// Option 2: Include the current string if it doesn't
// exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
let includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs, maxZeros - zeroCount,
maxOnes - oneCount);
maxSubset = Math.max(maxSubset, includeCurrent);
}
return maxSubset;
}
function maxSubsetSize(strs, maxZeros, maxOnes) {
const n = strs.length;
// Precompute the count of zeros in each string and
// store in zeroCounts array
const zeroCounts
= strs.map(str => str.split("0").length - 1);
// Start the recursive helper function from the first
// string
return findMaxSubsetSize(0, n, zeroCounts, strs, maxZeros,
maxOnes);
}
const arr = [ "1", "0", "0001", "10", "111001" ];
const a = 5, b = 3;
const res = maxSubsetSize(arr, a, b);
console.log(res);
Output
4
Using Memoization - O(n*a*b) Time and O(n*a*b) Space
If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming.
1. Optimal Substructure: The solution to the problem of finding the maximum subset of strings that satisfy exactly a zeros and b ones can be derived from the optimal solutions of smaller subproblems.
2. Overlapping Subproblems: When implementing a recursive approach to solve the problem of selecting strings with exactly a zeros and b ones, we observe that many subproblems are computed multiple times. Specifically, when we recursively solve for findMaxSubset(index, a, b), where a and b represent the remaining number of zeros and ones, the same subproblems might be recomputed several times.
- The recursive solution involves changing three parameters: the current index and the remaining count of zeros (a) and remaining count of ones (b). We need to track these three parameters, so we create a 3D array of size (n+1)x(a+1)x(b+1) because the value of n will be in range of [0, n] and remaining count of a will be in range [0, a] and remaining count of b will be in range [0, b].
- We initialize the 3D array with -1 to indicate that no subproblems have been computed yet.
- we check if the value at memo[n][a][b] is -1. if it is, we proceed to compute the result. otherwise, we return the stored result.
// C++ program to find the length of the longest subset
// using memoization
#include <iostream>
#include <vector>
using namespace std;
int findMaxSubsetSize(int index, int n, vector<int> &zeroCounts,
vector<string> &strs, int maxZeros, int maxOnes,
vector<vector<vector<int>>> &memo) {
// Base case: if we've processed all strings, return 0
if (index >= n)
return 0;
// if this state has already
// been computed, return its stored result
if (memo[index][maxZeros][maxOnes] != -1)
return memo[index][maxZeros][maxOnes];
// Option 1: Skip the current string
int maxSubset = findMaxSubsetSize(index + 1, n,
zeroCounts, strs,
maxZeros, maxOnes, memo);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].size() - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent =
1 + findMaxSubsetSize(index + 1, n,
zeroCounts, strs, maxZeros - zeroCount, maxOnes - oneCount, memo);
maxSubset = max(maxSubset, includeCurrent);
}
// Memoize the result for the current state and return it
return memo[index][maxZeros][maxOnes] = maxSubset;
}
int maxSubsetSize(vector<string> &strs, int maxZeros, int maxOnes) {
int n = strs.size();
// 3D DP array to memoize results,
// initialized to -1 for uncomputed states
vector<vector<vector<int>>> memo(n + 1,
vector<vector<int>>(maxZeros + 1, vector<int>(maxOnes + 1, -1)));
// Precompute the count of zeros
// in each string and store in zeroCounts array
vector<int> zeroCounts(n, 0);
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs[i]) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
return findMaxSubsetSize(0, n, zeroCounts,
strs, maxZeros, maxOnes, memo);
}
int main() {
vector<string> arr = {"1", "0", "0001", "10", "111001"};
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
cout << res;
return 0;
}
// Java program to find the length of the longest subset
// using memoization
import java.util.*;
class GfG {
static int findMaxSubsetSize(int index, int n,
int[] zeroCounts,
String[] strs, int maxZeros,
int maxOnes, int[][][] memo) {
// Base case: if we've processed all strings, return
// 0
if (index >= n)
return 0;
// Memoization check: if this state has already been
// computed, return its stored result
if (memo[index][maxZeros][maxOnes] != -1)
return memo[index][maxZeros][maxOnes];
// Option 1: Skip the current string
int maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes, memo);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].length() - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs,
maxZeros - zeroCount,
maxOnes - oneCount, memo);
maxSubset = Math.max(maxSubset, includeCurrent);
}
// Memoize the result for the current state and
// return it
memo[index][maxZeros][maxOnes] = maxSubset;
return maxSubset;
}
static int maxSubsetSize(String[] strs, int maxZeros,
int maxOnes) {
int n = strs.length;
// 3D DP array to memoize results, initialized to -1
// for uncomputed states
int[][][] memo
= new int[n + 1][maxZeros + 1][maxOnes + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= maxZeros; j++) {
Arrays.fill(memo[i][j], -1);
}
}
// Precompute the count of zeros in each string and
// store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs[i].toCharArray()) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Start the recursive helper function from the
// first string
return findMaxSubsetSize(0, n, zeroCounts, strs,
maxZeros, maxOnes, memo);
}
public static void main(String[] args) {
String[] arr = { "1", "0", "0001", "10", "111001" };
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
System.out.println(res);
}
}
# Python program to find the length of the longest subset
# using memoization
from typing import List
def findMaxSubsetSize(index: int, n: int, zeroCounts: \
List[int], strs: List[str], maxZeros: int,\
maxOnes: int, memo: List[List[List[int]]]) -> int:
# Base case: if we've processed all strings, return 0
if index >= n:
return 0
# Memoization check: if this state has
# already been computed, return its stored result
if memo[index][maxZeros][maxOnes] != -1:
return memo[index][maxZeros][maxOnes]
# Option 1: Skip the current string
maxSubset = findMaxSubsetSize(index + 1, n, zeroCounts,
strs, maxZeros, maxOnes, memo)
zeroCount = zeroCounts[index]
oneCount = len(strs[index]) - zeroCount
# Option 2: Include the current string if it doesn't
# exceed the max zeros and ones allowed
if zeroCount <= maxZeros and oneCount <= maxOnes:
includeCurrent = 1 + \
findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros - zeroCount, maxOnes - oneCount, memo)
maxSubset = max(maxSubset, includeCurrent)
# Memoize the result for the current state and return it
memo[index][maxZeros][maxOnes] = maxSubset
return maxSubset
def maxSubsetSize(strs: List[str], maxZeros: int, maxOnes: int) -> int:
n = len(strs)
# 3D DP array to memoize results,
# initialized to -1 for uncomputed states
memo = [[[-1] * (maxOnes + 1) for _ in range(maxZeros + 1)]
for _ in range(n + 1)]
# Precompute the count of zeros in each
# string and store in zeroCounts array
zeroCounts = [s.count('0') for s in strs]
# Start the recursive helper function
# from the first string
return findMaxSubsetSize(0, n, zeroCounts, strs, maxZeros, maxOnes, memo)
arr = ["1", "0", "0001", "10", "111001"]
a, b = 5, 3
res = maxSubsetSize(arr, a, b);
print(res)
// C# program to find the length of the longest subset
// using memoization
using System;
class GfG {
static int findMaxSubsetSize(int index, int n,
int[] zeroCounts,
string[] strs, int maxZeros,
int maxOnes, int[, , ] memo) {
// Base case: if we've processed all strings, return
// 0
if (index >= n)
return 0;
// Memoization check: if this state has already been
// computed, return its stored result
if (memo[index, maxZeros, maxOnes] != -1)
return memo[index, maxZeros, maxOnes];
// Option 1: Skip the current string
int maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes, memo);
int zeroCount = zeroCounts[index];
int oneCount = strs[index].Length - zeroCount;
// Option 2: Include the current string if it
// doesn't exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
int includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs,
maxZeros - zeroCount,
maxOnes - oneCount, memo);
maxSubset = Math.Max(maxSubset, includeCurrent);
}
// Memoize the result for the current state and
// return it
memo[index, maxZeros, maxOnes] = maxSubset;
return maxSubset;
}
static int maxSubsetSize(string[] strs, int maxZeros,
int maxOnes) {
int n = strs.Length;
// 3D DP array to memoize results, initialized to -1
// for uncomputed states
int[, , ] memo
= new int[n + 1, maxZeros + 1, maxOnes + 1];
for (int i = 0; i <= n; i++)
for (int j = 0; j <= maxZeros; j++)
for (int k = 0; k <= maxOnes; k++)
memo[i, j, k] = -1;
// Precompute the count of zeros in each string and
// store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
int countZeros = 0;
foreach(char c in strs[i]) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Start the recursive helper function from the
// first string
return findMaxSubsetSize(0, n, zeroCounts, strs,
maxZeros, maxOnes, memo);
}
public static void Main() {
string[] arr = { "1", "0", "0001", "10", "111001" };
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
Console.WriteLine(res);
}
}
// JavaScript program to find the length of the longest
// subset using memoization
function findMaxSubsetSize(index, n, zeroCounts, strs, maxZeros,
maxOnes, memo) {
// Base case: if we've processed all strings, return 0
if (index >= n) {
return 0;
}
// Memoization check: if this state has already been
// computed, return its stored result
if (memo[index][maxZeros][maxOnes] !== -1) {
return memo[index][maxZeros][maxOnes];
}
// Option 1: Skip the current string
let maxSubset
= findMaxSubsetSize(index + 1, n, zeroCounts, strs,
maxZeros, maxOnes, memo);
let zeroCount = zeroCounts[index];
let oneCount = strs[index].length - zeroCount;
// Option 2: Include the current string if it doesn't
// exceed the max zeros and ones allowed
if (zeroCount <= maxZeros && oneCount <= maxOnes) {
let includeCurrent
= 1
+ findMaxSubsetSize(index + 1, n, zeroCounts,
strs, maxZeros - zeroCount,
maxOnes - oneCount, memo);
maxSubset = Math.max(maxSubset, includeCurrent);
}
// Memoize the result for the current state and return
// it
memo[index][maxZeros][maxOnes] = maxSubset;
return maxSubset;
}
function maxSubsetSize(strs, maxZeros, maxOnes) {
const n = strs.length;
// 3D DP array to memoize results, initialized to -1 for
// uncomputed states
const memo = Array.from(
{length : n + 1},
() => Array.from(
{length : maxZeros + 1},
() => Array(maxOnes + 1).fill(-1)));
// Precompute the count of zeros in each string and
// store in zeroCounts array
const zeroCounts
= strs.map(str => str.split("0").length - 1);
// Start the recursive helper function from the first
// string
return findMaxSubsetSize(0, n, zeroCounts, strs, maxZeros,
maxOnes, memo);
}
const arr = [ "1", "0", "0001", "10", "111001" ];
const a = 5, b = 3;
const res = maxSubsetSize(arr, a, b);
console.log(res);
Output
4
Using Bottom-Up DP (Tabulation) - O(n*a*b) Time and O(n*a*b) Space
The approach is similar to the previous one. just instead of breaking down the problem recursively, we iteratively build up the solution by calculating in bottom-up manner where dp[i][j][k] represent the maximum size of the subset of the first i strings that can be formed using at most j zeros and k ones.
Base Case:
if i = 0, j = 0, k = 0
dp[i][j][k] = 0Recurrance relations:
if zeros[i-1] > j or ones[i-1] > k
dp[i][j][k] = dp[i-1][j][k]else
dp[i][j][k] = max(dp[i-1][j][k], 1 + dp[i-1][j-zeros[i-1]][k-ones[i-1]]) here, zeros[i-1] and ones[i-1] is the number of zeros and ones, respectively, in the (i-1)th string.
// C++ program to find the length of the longest subset
// using tabulation
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int maxSubsetSize(vector<string> &strs, int maxZeros, int maxOnes) {
int n = strs.size();
// 3D DP array to store results
vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>
(maxZeros + 1, vector<int>(maxOnes + 1, 0)));
// Precompute the count of zeros in each string
// and store in zeroCounts array
vector<int> zeroCounts(n, 0);
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs[i]) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Fill the DP table
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= maxZeros; j++) {
for (int k = 0; k <= maxOnes; k++) {
// Option 1: Don't include the current string
dp[i][j][k] = dp[i - 1][j][k];
// Option 2: Include the current string if it doesn't exceed
// the max zeros and ones
int zeroCount = zeroCounts[i - 1];
int oneCount = strs[i - 1].size() - zeroCount;
if (zeroCount <= j && oneCount <= k) {
dp[i][j][k] = max(dp[i][j][k], 1 + dp[i - 1][j - zeroCount][k - oneCount]);
}
}
}
}
// Return the result from the DP table
return dp[n][maxZeros][maxOnes];
}
int main() {
vector<string> arr = {"1", "0", "0001", "10", "111001"};
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
cout << res;
return 0;
}
// Java program to find the length of the longest subset
// using Tabulation
import java.util.*;
class GfG {
static int maxSubsetSize(List<String> strs,
int maxZeros,
int maxOnes) {
int n = strs.size();
// 3D DP array to store results
int[][][] dp
= new int[n + 1][maxZeros + 1][maxOnes + 1];
// Precompute the count of zeros in each string and
// store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
int countZeros = 0;
for (char c : strs.get(i).toCharArray()) {
if (c == '0')
countZeros++;
}
zeroCounts[i] = countZeros;
}
// Fill the DP table
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= maxZeros; j++) {
for (int k = 0; k <= maxOnes; k++) {
// Option 1: Don't include the current
// string
dp[i][j][k] = dp[i - 1][j][k];
// Option 2: Include the current string
// if it doesn't exceed the max zeros
// and ones
int zeroCount = zeroCounts[i - 1];
int oneCount = strs.get(i - 1).length()
- zeroCount;
if (zeroCount <= j && oneCount <= k) {
dp[i][j][k] = Math.max(
dp[i][j][k],
1
+ dp[i - 1][j - zeroCount]
[k - oneCount]);
}
}
}
}
// Return the result from the DP table
return dp[n][maxZeros][maxOnes];
}
public static void main(String[] args) {
List<String> arr = Arrays.asList("1", "0", "0001",
"10", "111001");
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
System.out.println(res);
}
}
# Python program to find the length of the longest subset
# using Tabulation
def maxSubsetSize(strs, maxZeros, maxOnes):
n = len(strs)
# 3D DP array to store results
dp = [[[0] * (maxOnes + 1) for _ in range(maxZeros + 1)]
for _ in range(n + 1)]
# Precompute the count of zeros in each
# string and store in zeroCounts array
zeroCounts = [0] * n
for i in range(n):
countZeros = strs[i].count('0')
zeroCounts[i] = countZeros
# Fill the DP table
for i in range(1, n + 1):
for j in range(maxZeros + 1):
for k in range(maxOnes + 1):
# Option 1: Don't include the current string
dp[i][j][k] = dp[i - 1][j][k]
# Option 2: Include the current string if
# it doesn't exceed the max zeros and ones
zeroCount = zeroCounts[i - 1]
oneCount = len(strs[i - 1]) - zeroCount
if zeroCount <= j and oneCount <= k:
dp[i][j][k] = max(dp[i][j][k], 1 + dp[i - 1]
[j - zeroCount][k - oneCount])
# Return the result from the DP table
return dp[n][maxZeros][maxOnes]
if __name__ == "__main__":
arr = ["1", "0", "0001", "10", "111001"]
a, b = 5, 3
res = maxSubsetSize(arr, a, b)
print(res)
// C# program to find the length of the longest subset
// using Tabulation
using System;
using System.Linq;
class GfG {
// Function to calculate the maximum subset size
static int maxSubsetSize(string[] strs, int maxZeros, int maxOnes) {
int n = strs.Length;
// 3D DP array to store the results
int[, ,] dp = new int[n + 1, maxZeros + 1, maxOnes + 1];
// Precompute the count of zeros in each
// string and store in zeroCounts array
int[] zeroCounts = new int[n];
for (int i = 0; i < n; i++) {
zeroCounts[i] = strs[i].Count(c => c == '0');
}
// Fill the DP table
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= maxZeros; j++) {
for (int k = 0; k <= maxOnes; k++) {
// Option 1: Don't include the current string
dp[i, j, k] = dp[i - 1, j, k];
// Option 2: Include the current string if
// it doesn't exceed the max zeros and ones
int zeroCount = zeroCounts[i - 1];
int oneCount = strs[i - 1].Length - zeroCount;
if (zeroCount <= j && oneCount <= k) {
dp[i, j, k] = Math.Max(dp[i, j, k],
1 + dp[i - 1, j - zeroCount, k - oneCount]);
}
}
}
}
// Return the result from the DP table (maximum subset size)
return dp[n, maxZeros, maxOnes];
}
static void Main() {
string[] arr = { "1", "0", "0001", "10", "111001" };
int a = 5, b = 3;
int res = maxSubsetSize(arr, a, b);
Console.WriteLine(res);
}
}
// JavaScript program to find the length of the longest
// subset using Tabulation
function maxSubsetSize(strs, maxZeros, maxOnes) {
const n = strs.length;
// 3D DP array to store results
const dp = Array.from(
{length : n + 1},
() => Array.from({length : maxZeros + 1},
() => Array(maxOnes + 1).fill(0)));
// Precompute the count of zeros in each string and
// store in zeroCounts array
const zeroCounts = strs.map(
str => str.split("").filter(c => c === "0").length);
// Fill the DP table
for (let i = 1; i <= n; i++) {
for (let j = 0; j <= maxZeros; j++) {
for (let k = 0; k <= maxOnes; k++) {
// Option 1: Don't include the current
// string
dp[i][j][k] = dp[i - 1][j][k];
// Option 2: Include the current string if
// it doesn't exceed the max zeros and ones
const zeroCount = zeroCounts[i - 1];
const oneCount
= strs[i - 1].length - zeroCount;
if (zeroCount <= j && oneCount <= k) {
dp[i][j][k] = Math.max(
dp[i][j][k],
1
+ dp[i - 1][j - zeroCount]
[k - oneCount]);
}
}
}
}
return dp[n][maxZeros][maxOnes];
}
const arr = [ "1", "0", "0001", "10", "111001" ];
const a = 5, b = 3;
const res = maxSubsetSize(arr, a, b);
console.log(res);
Output
4