474. 一和零
题目描述:给你一个二进制字符串数组 strs 和两个整数 m 和 n。请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1。如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的子集 。
思路:动态规划(在一定限定下求最值)
细节:用二维滚动数组来对应二个限制条件;先遍历物品,再遍历背包,并从后往前遍历
动态规划五部曲:
1. dp数组定义:dp[i][j]为有i个0和j个1的最大子集长度, dp = [[0] * (n+1) for _ in range(m+1)]
2. 递推公式:dp[i][j] = max(dp[i][j], dp[i-x][j-y] + 1),x和y为当前遍历到的整数中的0和1个数
3. 初始化:dp[0][0] = 0 obviously
4. 遍历顺序:先物品再背包,从后往前
5. 打印数组
复杂度:时间复杂度:O(lmn+L), l是数组strs的长度,L是数组strs中所有字符串的长度之和。
空间复杂的:O(mn)
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
dp = [[0] * (n+1) for _ in range(m+1)] # [0] * (n+1) 生成行向量
for str in strs:
ones = str.count('1')
zeros = str.count('0')
for i in range(m,zeros-1,-1):
for j in range(n,ones-1,-1):
dp[i][j] = max(dp[i][j], dp[i-zeros][j-ones]+1)
return dp[m][n]