474. Ones and Zeroes

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];
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值