Ones and Zeroes

Medium
Watch on YouTube ↗

Solution

/* Reursive Approach : Gives TLE*/

class Solution {
    // Time complexity : 2^strs.length * L 
    public int findMaxForm(String[] strs, int m, int n) {
        return helper(m, n, 0, strs);
    }

    int helper(int m, int n, int index, String[] strs) {
        // base condition
        if(index >= strs.length) {
            return 0;
        }

        // zeros, ones
        int[] count = func(strs[index]);
        int zeros = count[0];
        int ones = count[1];

        // 2 options, 
        int take = 0;
        if(zeros<=m && ones<=n) {
            take = 1 + helper(m-zeros, n-ones, index+1, strs);
        }
        int skip = helper(m, n, index+1, strs); // the size of subset

        int ans = Math.max(take, skip);
        return ans;

    }

    int[] func(String s) {
        int zeros = 0, ones = 0;
        for(char ch : s.toCharArray()) {
            if(ch=='0')
                zeros++;
            else ones++;
        }
        return new int[]{zeros, ones};
    }
}
/* Recursive With Memoization */
class Solution {
    int dp[][][];
    public int findMaxForm(String[] strs, int m, int n) {
        dp = new int[m+1][n+1][strs.length];
        for(int i=0; i<=m; i++) {
            for(int j=0; j<=n; j++) {
                for(int k=0; k<strs.length; k++) {
                    dp[i][j][k] = -1;
                }
            }
        }
        return helper(m, n, 0, strs);
    }

    int helper(int m, int n, int index, String[] strs) {
        // base condition
        if(index >= strs.length) {
            return 0;
        }

        if(dp[m][n][index]!=-1) {
            return dp[m][n][index];
        }

        // zeros, ones
        int[] count = func(strs[index]);
        int zeros = count[0];
        int ones = count[1];

        // 2 options, 
        int take = 0;
        if(zeros<=m && ones<=n) {
            take = 1 + helper(m-zeros, n-ones, index+1, strs);
        }
        int skip = helper(m, n, index+1, strs); // the size of subset

        int ans = Math.max(take, skip);
        dp[m][n][index] = ans;
        return ans;

    }

    int[] func(String s) {
        int zeros = 0, ones = 0;
        for(char ch : s.toCharArray()) {
            if(ch=='0')
                zeros++;
            else ones++;
        }
        return new int[]{zeros, ones};
    }
}


*/

/*Iterative Solution Approach */

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int[][] dp = new int[m + 1][n + 1];

        for (String s : strs) {
            int[] count = countZerosOnes(s);
            int zeros = count[0];
            int ones = count[1];

            // Traverse backwards to avoid reusing the same string multiple times
            for (int i = m; i >= zeros; i--) {
                for (int j = n; j >= ones; j--) {
                    dp[i][j] = Math.max(dp[i][j], 1 + dp[i - zeros][j - ones]);
                }
            }
        }

        return dp[m][n];
    }

    private int[] countZerosOnes(String s) {
        int zeros = 0, ones = 0;
        for (char c : s.toCharArray()) {
            if (c == '0') zeros++;
            else ones++;
        }
        return new int[]{zeros, ones};
    }
}