欢迎关注微信公众号:【没伞的孩子拼命跑】 和我的小伙伴们一块坚持打卡变大牛吧。
题目要求
题目解析
题目说的是给你m个0,n个1,让你求给定的字符串中,符合0的个数小于等于m,1的个数小于等于n的字符串的个数最大为多少?
解题思路
首先要想这个题的解题方法是什么?之前提到过凡是求最大,最小的,一般都是用动态规划。大家如果做过背包问题,其实对于这个题目还是有感觉的。背包问题是让装的东西小于V,而这个题是让0小于m,1小于n两个条件。经典的背包问题是用两个维度的数组,所以现在是用三个维度的数组
定义状态:dp[i][j][k] 表示输入字符串在子区间 [0, i] 能够使用 j 个 0 和 k 个 1 的字符串的最大数量。
dp[i-1][j][k] 不选择当前考虑的字符串,至少是这个数值
dp[i][j][k]={dp[i−1][j][k],dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1 选择当前考虑的字符串。
其实你会发现,前行只参考了上一行的值,因此可以使用滚动数组,也可以从后向前赋值。
AC代码和详细注释如下
//C++题解 //从后往前赋值
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>>dp(m+1,vector<int>(n+1,0));
int num1=0;//1的个数
int num0=0;//2的个数
for(auto str:strs)
{
num0=0;
num1=0;
//得到每个字符串中1的个数和0的个数
for(int i = 0;i<str.size();i++)
{
if(str[i]=='0')
num0++;
else num1++;
}
//实现时,内层循环需采用倒序遍历的方式,这种方式保证转移来的是
//dp[i-1][][]dp[i−1][][] 中的元素值
for(int i = m;i>=num0;i--)
{
for(int j = n;j>=num1;j--)
{
dp[i][j] = max(dp[i][j],dp[i-num0][j-num1]+1);
}
}
}
return dp[m][n];
}
};
通过情况