题目: 一和零
- 在计算机界中,我们总是追求用有限的资源获取最大的收益。
- 现在,假设你分别支配着 m 个
0
和 n 个 1。另外,还有一个仅包含 0 和 1 字符串的数组。
- 你的任务是使用给定的
m
个0
和n
个1
,找到能拼出存在于数组中的字符串的最大数量。每个0
和1
至多被使用一次。
注意:
- 给定
0
和1
的数量都不会超过100。
- 给定字符串数组的长度不会超过600。
示例 1:
输入: Array = {"10", "0001", "111001", "1", "0"},m = 5, n = 3
输出: 4
解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出,即 "10","0001","1","0" 。
示例 2:
输入: Array = {"10", "0", "1"}, m = 1, n = 1
输出: 2
解释: 你可以拼出 "10",但之后就没有剩余数字了。更好的选择是拼出 "0" 和 "1" 。
来源:力扣(LeetCode)第474题
链接:https://leetcode-cn.com/problems/ones-and-zeroes
分析:
- 典型的背包问题,有两个状态,i是当0有i个时,j是当1有j个时。
- 我们举出小于m和小于n的0和1的个数。每当一个str进来时有两种选择,一种是放进去,另一种不放。
- 如果放进去,那么放完后还要加上
i-count(0)
和j-count(1)
时候的个数,如果不放就不用动它。比较两者谁大,把大的存在当前状态。
- 我们每次把所有状态都更新一遍。
代码:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1];
for (String str : strs) {
int zero = 0, one = 0;
// 找到0 和 1的个数
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '1') one++;
else zero++;
}
// 如果str的0和1的个数是x,y,那么我们将能够装下x个0,和y个1的状态依次进行比较。
// 如果装下x个0, y个1后,然后查看剩下的i-x个0和j-y个1能装下几个,这个状态在上一次已经算过了。
for (int i = m; i >= zero; i--)
for (int j = n; j >= one; j--)
dp[i][j] = Math.max(dp[i][j], dp[i-zero][j-one] + 1);
}
return dp[m][n];
}
}