关键词:动态规划 01背包
一个套路:
- 01背包:空间优化之后dp【target+1】,遍历的时候要逆序遍历
- 完全背包:空间优化之后dp【target+1】,遍历的时候要正序遍历
目录
题目:
思路:
复杂度计算:
代码:
题目:
思路:
这题能想到用01背包并正确用起来有点难哦!
这里面有三样东西,一些strs,m个0和n个1。
我刚开始是希望把strs当作容器,把0和1装进strs这个容器里,但是不行。
转换思路:把m个0和n个1作为两个容器,strs里的0和1分别装进这两个容器里。
因为有两个容器,所以dp得要两个维度dp[m+1][n+1]
其他都和一维的01背包一样
状态:dp[j][k] 前i个str中,使用 j个 0 和 k 个 1 的情况下最多可以得到的字符串数量。
转移方程:dp[j][k]=max(dp[j][k],dp[j-zeros][k-ones]+1)【zeros、ones:第i个str0和1的个数】
- 如果选dp[j][k]:不要第i个str,维持上一个str的状态。
- 如果选dp[j-zeros][k-ones]+1:要第i个str,数量+1。
初始化:dp[j][k]=0 因为是求最大
复杂度计算:
时间复杂度O(lmn+L) l=strs.size() L=所有str的字符总数(统计了每个str的01数量)
空间复杂度O(mn)
代码:
class Solution {
public:
int findMaxForm(std::vector<std::string>& strs, int m, int n) {
std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1));
for (const auto& str:strs)
{
int zeros = 0, ones = 0;
for (const auto& c : str)
{
if (c == '0')++zeros;
else ++ones;
}
for (int j = m; j >= zeros; --j)
{
for (int k = n; k >= ones; --k)
{
dp[j][k] = std::max(dp[j][k], dp[j - zeros][k - ones] + 1);
}
}
}
return dp[m][n];
}
};