这是我参与更文挑战的第5天,活动详情查看更文挑战
题目描述
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.
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 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.length600 - 1
strs[i].length100 strs[i]consists only of digits '0' and '1'.- 1
m,n100
解题思路
这道题和经典的背包问题非常相似,但是和经典的背包问题只有一种容量不同,这道题有两种容量,即选取的字符串子集中的 和 的数量上限。
经典的背包问题可以使用二维动态规划求解,两个维度分别是物品和容量。这道题有两种容量,因此需要使用三维动态规划求解,三个维度分别是字符串、 的容量和 的容量。
定义三维数组 ,其中 表示在前 个字符串中,使用 个 和 个 的情况下最多可以得到的字符串数量。假设数组 strs 的长度为 ,则最终答案为
当没有任何字符串可以使用时,可以得到的字符串数量只能是 ,因此动态规划的边界条件是:当 时,对任意 和 ,都有
当 时,对于 strs 中的第 个字符串(计数从 开始),首先遍历该字符串得到其中的 和 的数量,分别记为 zeros 和 ones,然后对于 和 ,计算 的值。
当 和 的容量分别是 和 时,考虑以下两种情况:
如果 或 ,则不能选第 个字符串,此时有 ;
如果 且 ,则如果不选第 个字符串,有 ,如果选第 个字符串,有 , 的值应取上面两项中的最大值。
代码
C++代码
class Solution {
public:
vector<int> getZerosOnes(string& str) {
vector<int> zerosOnes(2);
int length = str.length();
for (int i = 0; i < length; i++) {
zerosOnes[str[i] - '0']++;
}
return zerosOnes;
}
int findMaxForm(vector<string>& strs, int m, int n) {
int length = strs.size();
vector<vector<vector<int>>> dp(length + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));
for (int i = 1; i <= length; i++) {
vector<int>&& zerosOnes = getZerosOnes(strs[i - 1]);
int zeros = zerosOnes[0], ones = zerosOnes[1];
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
dp[i][j][k] = dp[i - 1][j][k];
if (j >= zeros && k >= ones) {
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - zeros][k - ones] + 1);
}
}
}
}
return dp[length][m][n];
}
};