玩命加载中 . . .

474-一和零


LeetCode 474. 一和零

给你一个二进制字符串数组 strs 和两个整数 mn

请你找出并返回 strs 的最大子集的长度,该子集中 最多m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

Example 1:

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5031 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"}{"10","1","0"}{"111001"} 不满足题意,因为它含 41 ,大于 n 的值 3

method

0的数量和1的数量是两个维度的背包

dp[i][j]:0的数量最大为i,1的数量最大为j时的最大子集数

当前物品0的数量为zeorNum,1的数量为oneNum,考虑放不放当前物品,不放的话dp[i][j]不变,放的话,背包容量分别减少,即i-zeroNum, j-oneNum,然后子集数再+1,两者取较大值
所以递推公式是

dp[i][j] = max(dp[i][j], dp[i-zeroNum][j-oneNum] + 1)

求最多能装多少个的一般公式是:dp[j]=max(dp[j],dp[j-nums[i]]+1)

int findMaxForm(vector<string>& strs, int m, int n) {
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    for (auto str : strs) {
        int zeroNum = 0;
        int oneNum = 0;
        for (auto c : str) {
            if (c == '0') zeroNum++;
            else oneNum++;      // 统计0和1的数量
        }
        for (int i = m; i >= zeroNum; i--) {        // 0的背包
            for (int j = n; j >= oneNum; j--) {     // 1的背包
                dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
            }
        }
    }
    return dp[m][n];
}

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录