题目描述:
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
方法一:
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> count(strs.size(), vector<int>(2, 0));
//count[i][0]表示strs[i]中字符'0'的个数,count[i][1]表示strs[i]中字符'1'的个数
for (int i = 0; i < strs.size(); i++)
{
for (int j = 0; j < strs[i].size(); j++)
{
if (strs[i][j] == '0') count[i][0]++;
else count[i][1]++;
}
}
vector<vector<int>> f(m + 1, vector<int>(n + 1, 0));
//f[j][k]表示最大子集的大小,最大子集中的元素最多有j个0,最多有k个1
for (int i = 0; i < strs.size(); i++)
{
for (int j = m; j >= count[i][0]; j--)
{
for (int k = n; k >= count[i][1]; k--)
{
f[j][k] = max(f[j][k], f[j - count[i][0]][k - count[i][1]] + 1);
}
}
}
return f[m][n];
}
};
泪目,终于有一道01背包问题是自己写出来了。这道题比较值得注意的就是这里有两个限制条件:0的数量和1的数量,也就是相当于有两个背包容量的限制,因此至少需要二维的vector来解决。
先定义数组count,其中count[i][0]表示strs[i]中字符'0'的个数,count[i][1]表示strs[i]中字符'1'的个数,类比于背包问题中的物品重量。
设f[i][j]表示最大子集的大小,最大子集中的元素最多有j个0,最多有k个1。而最大子集的大小类比于背包问题中的物品价值,我们的目标是使得最大子集的大小越大越好。
根据f[i][j]的定义,有如下递推关系式:
f[j][k] = max(f[j][k], f[j - count[i][0]][k - count[i][1]] + 1);
前者表示不取当前遍历到的子集,后者表示取当前遍历到的子集(注意取之后,子集的个数+1)。