474. Ones and Zeroes - Explanation

Problem Link



1. Recursion

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        arr = [[0] * 2 for _ in range(len(strs))]
        for i, s in enumerate(strs):
            for c in s:
                arr[i][ord(c) - ord('0')] += 1

        def dfs(i, m, n):
            if i == len(strs):
                return 0

            res = dfs(i + 1, m, n)
            if m >= arr[i][0] and n >= arr[i][1]:
                res = max(res, 1 + dfs(i + 1, m - arr[i][0], n - arr[i][1]))
            return res

        return dfs(0, m, n)

Time & Space Complexity

  • Time complexity: O(2N)O(2 ^ N)
  • Space complexity: O(N)O(N) for recursion stack.

Where NN represents the number of binary strings, and mm and nn are the maximum allowable counts of zeros and ones, respectively.


2. Dynamic Programming (Top-Down)

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        arr = [[0] * 2 for _ in range(len(strs))]
        for i, s in enumerate(strs):
            for c in s:
                arr[i][ord(c) - ord('0')] += 1

        dp = {}

        def dfs(i, m, n):
            if i == len(strs):
                return 0
            if m == 0 and n == 0:
                return 0
            if (i, m, n) in dp:
                return dp[(i, m, n)]

            res = dfs(i + 1, m, n)
            if m >= arr[i][0] and n >= arr[i][1]:
                res = max(res, 1 + dfs(i + 1, m - arr[i][0], n - arr[i][1]))
            dp[(i, m, n)] = res
            return res

        return dfs(0, m, n)

Time & Space Complexity

  • Time complexity: O(mnN)O(m * n * N)
  • Space complexity: O(mnN)O(m * n * N)

Where NN represents the number of binary strings, and mm and nn are the maximum allowable counts of zeros and ones, respectively.


3. Dynamic Programming (Bottom-Up)

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        arr = [[0] * 2 for _ in range(len(strs))]
        for i, s in enumerate(strs):
            for c in s:
                arr[i][ord(c) - ord('0')] += 1

        dp = [[[0] * (n + 1) for _ in range(m + 1)] for _ in range(len(strs) + 1)]

        for i in range(1, len(strs) + 1):
            for j in range(m + 1):
                for k in range(n + 1):
                    dp[i][j][k] = dp[i - 1][j][k]
                    if j >= arr[i - 1][0] and k >= arr[i - 1][1]:
                        dp[i][j][k] = max(dp[i][j][k], 1 + dp[i - 1][j - arr[i - 1][0]][k - arr[i - 1][1]])

        return dp[len(strs)][m][n]

Time & Space Complexity

  • Time complexity: O(mnN)O(m * n * N)
  • Space complexity: O(mnN)O(m * n * N)

Where NN represents the number of binary strings, and mm and nn are the maximum allowable counts of zeros and ones, respectively.


4. Dynamic Programming (Space Optimized)

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        arr = [[0, 0] for _ in range(len(strs))]
        for i, s in enumerate(strs):
            for c in s:
                arr[i][ord(c) - ord('0')] += 1

        dp = [[0] * (n + 1) for _ in range(m + 1)]

        for zeros, ones in arr:
            for j in range(m, zeros - 1, -1):
                for k in range(n, ones - 1, -1):
                    dp[j][k] = max(dp[j][k], 1 + dp[j - zeros][k - ones])

        return dp[m][n]

Time & Space Complexity

  • Time complexity: O(mnN)O(m * n * N)
  • Space complexity: O(mn+N)O(m * n + N)

Where NN represents the number of binary strings, and mm and nn are the maximum allowable counts of zeros and ones, respectively.