算法: 1和0子集合的个数 474. Ones and Zeroes

Posted AI架构师易筋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法: 1和0子集合的个数 474. Ones and Zeroes相关的知识,希望对你有一定的参考价值。

474. Ones and Zeroes

You are given an array of binary strings strs and two integers m and n.

Return the size of the largest subset of strs such that there are at most m 0’s and n 1’s in the subset.

A set x is a subset of a set y if all elements of x are also elements of y.

Example 1:

Input: strs = ["10","0001","111001","1","0"], m = 5, n = 3
Output: 4
Explanation: The largest subset with at most 5 0's and 3 1's is "10", "0001", "1", "0", so the answer is 4.
Other valid but smaller subsets include "0001", "1" and "10", "1", "0".
"111001" is an invalid subset because it contains 4 1's, greater than the maximum of 3.

Example 2:

Input: strs = ["10","0","1"], m = 1, n = 1
Output: 2
Explanation: The largest subset is "0", "1", so the answer is 2.

Constraints:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] consists only of digits '0' and '1'.
  • 1 <= m, n <= 100

0,1背包问题,动态规划解法

理解这道题:找出子集合,子集合中所用到的0的总数小于m,并且1的总数小于n 。
0,1背包问题, 递推公式为 dp[r][c] = max(dp[r][c], dp[r-zeros][c-ones] + 1)

  • dp[r][c] 表示不用当前方案,维持上个版本的值
  • dp[r-zeros][c-ones] + 1 表示用当前方案,并且看以往用了该方案的基础上+1.

这个问题是0-1 背包问题的变体:每件物品都有一个二维重量,但值是恒定的。如果我们天真地尝试最多600 个字符串的每个排列,那将是2^600个排列。

但值得庆幸的是,我们的任务不是跟踪每个排列,而只是跟踪最大项目数。这需要使用动态规划( DP ) 来降低整体复杂性,而是只跟踪在努力寻找最终答案时遇到的各种子问题的最佳结果。

对于我们的 DP 数组 ( dp ),dp[r][c]将表示可以添加以产生r个零和c个 1 的最大项目数。因此,我们的答案最终将是dp[m][n]。我们自然会采用自下而上的 DP 方法,因为我们将从无数据开始并遍历输入数组 ( S ),在进行过程中向dp添加更多数据。

由于S中的每个字符串都需要我们遍历整个dp以查找要更新的数据,因此我们需要以自上而下的方式进行此迭代,以避免干扰我们的整体自下而上方法,这会发生如果我们要更新条目,这些条目将成为同一通道中以后更新的基础。

一旦我们到达终点,我们就会返回dp[m][c]

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        dp = [[0] * (n+1) for _ in range(m+1)]
        for s in strs:
            zeros = s.count("0")
            ones = len(s) - zeros
            for r in range(m, zeros - 1, -1):
                for c in range(n, ones - 1, -1):
                    dp[r][c] = max(dp[r][c], dp[r-zeros][c-ones] + 1)
        return dp[-1][-1]

参考

https://leetcode.com/problems/ones-and-zeroes/discuss/1138696/Ones-and-Zeros-or-JS-Python-Java-C%2B%2B-or-Easy-DP-Knapsack-Solution-w-Explanation

以上是关于算法: 1和0子集合的个数 474. Ones and Zeroes的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 474. Ones and Zeroes 一和零(中等)

leetcode 474. 一和零(01背包问题)

474. Ones and Zeroes

数据结构(四十四)插入排序(1.直接插入排序 2.希尔排序)

Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes)

算法设计与分析——划分问题(动态规划)