0474. 一和零【中等】
1. 📝 题目描述
给你一个二进制字符串数组 strs 和两个整数 m 和 n。
请你找出并返回 strs 的最大子集的长度,该子集中最多有 m 个 0 和 n 个 1。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的子集。
示例 1:
txt
输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:41
2
2
解释:
- 最多有 5 个 0 和 3 个 1 的最大子集是
{"10", "0001", "1", "0"},因此答案是 4。 - 其他满足题意但较小的子集包括
{"0001", "1"}和{"10", "1", "0"}。{"111001"}不满足题意,因为它含 4 个 1,大于 n 的值 3。
示例 2:
txt
输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:21
2
2
解释:
- 最大的子集是
{"0", "1"},所以答案是 2。
提示:
1 <= strs.length <= 6001 <= strs[i].length <= 100strs[i]仅由'0'和'1'组成1 <= m, n <= 100
2. 🎯 s.1 - 二维 0-1 背包 DP
c
int findMaxForm(char** strs, int strsSize, int m, int n) {
int** dp = (int**)malloc(sizeof(int*) * (m + 1));
for (int i = 0; i <= m; i++) {
dp[i] = (int*)calloc(n + 1, sizeof(int));
}
for (int k = 0; k < strsSize; k++) {
int zeros = 0, ones = 0;
for (char* p = strs[k]; *p; p++) *p == '0' ? zeros++ : ones++;
for (int i = m; i >= zeros; i--)
for (int j = n; j >= ones; j--)
if (dp[i - zeros][j - ones] + 1 > dp[i][j])
dp[i][j] = dp[i - zeros][j - ones] + 1;
}
int res = dp[m][n];
for (int i = 0; i <= m; i++) free(dp[i]);
free(dp);
return res;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
js
/**
* @param {string[]} strs
* @param {number} m
* @param {number} n
* @return {number}
*/
var findMaxForm = function (strs, m, n) {
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
for (const s of strs) {
let zeros = 0,
ones = 0
for (const ch of s) ch === '0' ? zeros++ : ones++
for (let i = m; i >= zeros; i--) {
for (let j = n; j >= ones; j--) {
dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1)
}
}
}
return dp[m][n]
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
py
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 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]1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 时间复杂度:
,其中 是字符串数量 - 空间复杂度:
算法思路:
- 每个字符串是一个物品,代价是其中 0 和 1 的个数
dp[i][j]表示最多使用 个 0 和 个 1 时能选取的最大字符串数,在计算过程中,dp[i][j]只会增加,不会减少- 状态转移:
dp[i][j] = max(dp[i][j], dp[i - zeros][j - ones] + 1)dp[i][j]若子串不进入集合的情况dp[i - zeros][j - ones] + 1若子串进入集合的情况
- 逆序遍历更新,保证每个字符串只被选一次