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

leetcode 2021/06/06 每日一题 https://leetcode-cn.com/problems/ones-and-zeroes

  1. 一和零

给你一个二进制字符串数组 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. 数组长度c,m个0,n个1
  2. 使用一个cmn的三维数组记录dp[k][i][j]
  3. 初始化:dp = [[[0]*(n+1) for _ in range(m+1)] for _ in range(c+1)]
  4. 边界:k=0 或 (i=0 或j=0) 时,dp[k][i][j] = 0
  5. 外层循环:k个元素,从1到c循环
  6. 中层循环:i个0,从1到m循环
  7. 内层循环:j个1,从1到n循环
  8. 第k个元素为s,0的个数为 s0 = s.count('0'),1的个数为 s1 = s.count('1')
  9. 当s0 > i or s1 > j:dp[k][i][j] = dp[k-1][i][j]
  10. else:dp[k][i][j] = max(dp[k-1][i][j], dp[k-1][i-s0][j-s1]+1)

python代码

def findMaxForm(strs, m, n):
    c = len(strs)
    dp = [[[0]*(n+1) for _ in range(m+1)] for _ in range(c+1)]
    for k in range(1, c+1):
        s0 = strs[k-1].count('0')
        s1 = strs[k-1].count('1')
        for i in range(1, m+1):
            for j in range(1, n+1):
                if i < s0 or j < s1:
                    dp[k][i][j] = dp[k - 1][i][j]
                else:
                    dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - s0][j - s1] + 1)
    return dp[c][m][n]


print(findMaxForm(["10", "0001", "111001", "1", "0"], 5, 3))
print(findMaxForm(["10", "0", "1"], 1, 1))

优化思路

使用二维数组,只需存储上一层dp[i-s0][j-s1],逆序更新
参考动态规划之01背包问题

优化python代码

def findMaxForm(strs, m, n):
    dp = [[0 for _ in range(n+1)] for _ in range(m+1)]
    for s in strs:
        s0 = s.count('0')
        s1 = s.count('1')
        for i in range(m, s0-1, -1):
            for j in range(n, s1-1, -1):
                dp[i][j] = max(dp[i][j], dp[i-s0][j-s1]+1)
    return dp[m][n]

print(findMaxForm(["10", "0001", "111001", "1", "0"], 5, 3))
print(findMaxForm(["10", "0", "1"], 1, 1))

运行结果:

posted @ 2021-06-10 23:53  ikventure  阅读(121)  评论(0编辑  收藏  举报