【Leetcode】474. Ones and Zeroes

题目地址:

https://leetcode.com/problems/ones-and-zeroes/

给定一个长 n n n字符串数组 A A A,里面的字符串只含 0 0 0 1 1 1。再给定两个正整数 u u u v v v,要求取出最多的字符串,使得 0 0 0的总数不超过 u u u并且 1 1 1的总数不超过 v v v,问最多能取多少个字符串。

思路是动态规划。设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]是只从前 i i i个字符串里选的话,要求 0 0 0的总数不超过 j j j并且 1 1 1的总数不超过 k k k的情况下,能选出的最多字符串个数。初始条件 f [ 0 ] f[0] f[0]都是 0 0 0,设第 i i i个字符串有 x x x 0 0 0 y y y 1 1 1,可以按照第 i i i个字符串选不选来分类,则有: f [ i ] [ j ] [ k ] = max ⁡ { f [ i − 1 ] [ j ] [ k ] , 1 + f [ i − 1 ] [ j − x ] [ k − y ] } f[i][j][k]=\max\{f[i-1][j][k],1+f[i-1][j-x][k-y]\} f[i][j][k]=max{f[i1][j][k],1+f[i1][jx][ky]}代码里可以用滚动数组优化,但 j j j k k k的两维要从大到小更新。代码如下:

public class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int len = strs.length;
        int[][] dp = new int[m + 1][n + 1];
        int[] cost0 = new int[len], cost1 = new int[len];
        for (int i = 0; i < len; i++) {
            String s = strs[i];
            for (int j = 0; j < s.length(); j++) {
                if (s.charAt(j) == '0') {
                    cost0[i]++;
                } else {
                    cost1[i]++;
                }
            }
        }
        
        for (int i = 1; i <= len; i++) {
            for (int j = m; j >= cost0[i - 1]; j--) {
                for (int k = n; k >= cost1[i - 1]; k--) {
                    dp[j][k] = Math.max(dp[j][k], 1 + dp[j - cost0[i - 1]][k - cost1[i - 1]]);
                }
            }
        }
        
        return dp[m][n];
    }
}

时间复杂度 O ( n u v ) O(nuv) O(nuv),空间 O ( u v ) O(uv) O(uv)

C++:

class Solution {
 public:
  int findMaxForm(vector<string>& strs, int m, int n) {
    vector<vector<int>> f(m + 1, vector<int>(n + 1));
    for (auto& s : strs) {
      int n0 = 0, n1 = 0;
      for (auto& ch : s)
        if (ch == '0') n0++;
        else n1++;
      
      for (int i = m; i >= n0; i--)
        for (int j = n; j >= n1; j--)
          f[i][j] = max(f[i][j], f[i - n0][j - n1] + 1);
    }

    return f[m][n];
  }
};

时空复杂度一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值