https://leetcode.com/problems/ones-and-zeroes/
Given an array, strs
, with strings consisting of only 0s
and 1s
. Also two integers m
and n
.
Now your task is to find the maximum number of strings that you can form with given m 0s
and n 1s
. Each 0
and 1
can be used at most once.
Example 1:
Input: strs = ["10","0001","111001","1","0"], m = 5, n = 3 Output: 4 Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are "10","0001","1","0".
Example 2:
Input: strs = ["10","0","1"], m = 1, n = 1 Output: 2 Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1".
Constraints:
1 <= strs.length <= 600
1 <= strs[i].length <= 100
strs[i]
consists only of digits '0' and '1'.1 <= m, n <= 100
算法思路:
- 0-1背包问题的扩展:多维费用背包问题,这里限制了2个维度,且我们分别考虑[0-k]个物品,因此总共三个维度,函数形式dp(k,m,n)
- 在第k个string加入备选项进行考虑时,dp[k][i][j]表示在使用不超过i个0和不超过j个1的情况下可以收录的最多string数目
- dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - cnt0][j - cnt1] + 1); //O(cmn) (c = strs.size())
- 从后往前计算优化空间为O(mn),不需要对k进行考虑,因为后面更改不会影响前面的k-1次dp[i][j]数值
//从大的背包到校的背包,也就是从后往前,可以统一操作
//如果从前往后,由于k次dp[i][j]会依赖k-1次的dp[i][j]
//在本行会更改k-1次的dp[i][j]为k次的dp[i][j],先前dp[i][j]数据丢失
//造成后面位置使用的是k次dp[i][j]而不是k-1次的dp[i][j]
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); //dp[m][n]
int cnt0, cnt1;
for(string str : strs){
cnt0 = 0;
cnt1 = 0;
for(int k = 0; k < str.size(); k++){
if(str[k] == '0') cnt0++;
else cnt1++;
}
for(int i = m; i >= cnt0; i--){
for(int j = n; j >= cnt1; j--){
dp[i][j] = max(dp[i][j], dp[i - cnt0][j - cnt1] + 1);
}
}
}
return dp[m][n];
}
};