leetcode系列
文章目录
- 一、核心操作
- 二、外层配合操作
- 三、核心模式代码
- 总结
本题是一个01背包问题,只是背包是一个二维数组的背包,分别为0的个数不能超过m,1的个数不能超过n,而物品就是题目中的字符串,其容量为0和1的个数,而价值就是1,本题要在给定的背包容量中,使得价值尽可能的高,也就是尽可能多的拿字符串
一、核心操作
- dp[i][j]代表0的个数不超过i,1的个数不超过j的情况下,字符串的最大数量
- 递推公式:当本次拿取的字符串不超过背包容量时,可以比较是不拿这个字符串的的总共数量多,还是拿这个字符串的总共数量多,即比较dp[i][j]和dp[i-zero][j-one]+1;如果超过了背包容量那就不用比较了,直接就不用动了(因为是滚动数组,每一次都直接在上一层的基础上更新)
- 初始化:由于个数是从0开始的,都初始化为0就可以
- 遍历顺序:两个都是从后往前,只有这样才不会重复放入字符串
提示:小白个人理解,如有错误敬请谅解!
二、外层配合操作
- 每次都从字符串数组中拿取一个,统计这个字符串0和1的数量,然后根据这个来更新本层的数据
三、核心模式代码
代码如下:
class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(string str : strs){int zero=0;int one=0;for(auto & s :str){if(s=='0')zero++;else one++;}for(int i=m;i>=zero;i--){for(int j=n;j>=one;j--){dp[i][j]=max(dp[i][j],dp[i-zero][j-one]+1);}}}return dp[m][n];}
};
总结
- 其实按照标准的01背包来看,此题应该用一个三维数组,但是三维数组对资源占用太大了,代码如下:
class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<vector<int>>> dp (strs.size(),vector<vector<int>>(m+1,vector<int>(n+1,0)));vector<int> zero;vector<int> one;for(string str : strs){int zeroNum=0;int oneNum=0;for(char s : str){if(s=='0')zeroNum++;else oneNum++;}one.push_back(oneNum);zero.push_back(zeroNum);}if(zero[0]<=m && one[0]<=n){for(int j=zero[0];j<=m;j++){for(int k=one[0];k<=n;k++){dp[0][j][k]=1;}}}for(int i=1;i<strs.size();i++){for(int j=0;j<=m;j++){for(int k=0;k<=n;k++){if(j<zero[i] || k<one[i])dp[i][j][k]=dp[i-1][j][k];else dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-zero[i]][k-one[i]]+1);}}}return dp[strs.size()-1][m][n];}
};