[Leetcode] 474. Ones and Zeroes 解题报告

本文介绍了一种使用动态规划解决的问题,即如何利用限定数量的0和1形成尽可能多的字符串组合。通过具体实例展示了算法的设计思路及实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

In the computer world, use restricted resource you have to generate maximum benefit is what we always want to pursue.

For now, suppose you are a dominator of m 0s and n 1s respectively. On the other hand, there is an array with strings consisting of only 0s and 1s.

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.

Note:

  1. The given numbers of 0s and 1s will both not exceed 100
  2. The size of given string array won't exceed 600.

Example 1:

Input: Array = {"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: Array = {"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".

思路

又是动态规划的一个变种。我们定义dp[i][j]表示从第0个字符串到截止当前字符串,用i个0和j个1可以构成的字符串的最大数目。那么状态转移方程是:dp[i][j] = max(dp[i - zero_num][j - one_num]),其中zero_num和one_num分别是当前字符串中0和1的数目,i <= zero_num <= m, j <= one_num <= n。需要注意的是:我们必须从后往前更新,这是因为如果从前往后更新,那么如果更新了dp[i][j],就意味着当前dp[i][j]的数量已经包含了s,那么在计算dp[i + ...][j + ...]的时候,用到的dp[i][j]是已经被更新过的(也就是包含了s的数量),所以就会导致重复计算。

算法的时间复杂度是O(l * m * n),其中l是字符串的数量。算法的空间复杂度是O(m*n)。

代码

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        for (auto &s : strs) {
            int numZeroes = 0, numOnes = 0;
            for (auto c : s) {
                if (c == '0')
                    numZeroes++;
                else if (c == '1')
                    numOnes++;
            }
            for (int i = m; i >= numZeroes; i--) {
                for (int j = n; j >= numOnes; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - numZeroes][j - numOnes] + 1);
                }
            }
        }
        return dp[m][n];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值