题目
难度:★★★☆☆
类型:数组
方法:动态规划
力扣链接请移步本题传送门
更多力扣中等题的解决方案请移步力扣中等题目录
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
示例
示例 1:
输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。
示例 2:
输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。
提示:
1 <= strs.length <= 600
1 <= strs[i].length <= 100
strs[i] 仅由 '0' 和 '1' 组成
1 <= m, n <= 100
解答
这是典型的零一背包问题的变体。首先来回顾一下零一背包
,这道题目变化的是,限制从一个变成了两个,因此我们可以考虑建立二维dp数组。
数组定义:定义一个mxn维的数组dp,其中dp[i][j]表示在最大0的个数为i,1的个数为j时,最大子集的个数。
初始状况:dp数组所有元素都初始化为零。
递推公式:当某一个字符串中零和一的个数都不超过最大限制的个数(zero_max,one_max)时,更新:
dp[zero_max][one_max] = max(dp[zero_max][one_max], dp[zero_max-zero_num][one_max-one_num]+1)
最终情况:选择dp数组最右下角的结果即可。
【思考】遍历过程为什么需要逆序?
class Solution:
def findMaxForm(self, strs, m: int, n: int) -> int:
dp = [[0 for _ in range(n+1)] for _ in range(m+1)]
for s in strs:
zero_num, one_num = s.count('0'), s.count('1')
for zero_max in reversed(range(0, m+1)):
for one_max in reversed(range(0, n+1)):
if zero_num <= zero_max and one_num <= one_max:
dp[zero_max][one_max] = max(dp[zero_max][one_max], dp[zero_max-zero_num][one_max-one_num]+1)
return dp[-1][-1]
如有疑问或建议,欢迎评论区留言~
有关更多力扣中等题的python解决方案,请移步力扣中等题解析
网友评论