1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Solution {
private Integer[][][] memo;

public int findMaxForm(String[] strs, int m, int n) {
int[][] charCount = new int[strs.length][2];
for (int i = 0; i < charCount.length; i++) {
String currString = strs[i];
int ones = countOne(currString);
int zeroes = currString.length() - ones;
charCount[i][0] = zeroes;
charCount[i][1] = ones;
}
memo = new Integer[strs.length][m + 1][n + 1];
return dfs(charCount, 0, m, n);
}

private int dfs(int[][] charCount, int pos, int remainM, int remainN) {
if (pos == charCount.length) {
return 0;
}
if (memo[pos][remainM][remainN] != null) {
return memo[pos][remainM][remainN];
}
int taken = 0;
if (remainM - charCount[pos][0] >= 0 && remainN - charCount[pos][1] >= 0) {
taken = dfs(charCount, pos + 1, remainM - charCount[pos][0], remainN - charCount[pos][1]) + 1;
}
int notTaken = dfs(charCount, pos + 1, remainM, remainN);
return memo[pos][remainM][remainN] = Math.max(taken, notTaken);

}

private int countOne(String s) {
char[] sArray = s.toCharArray();
int ans = 0;
for (char c : sArray) {
if (c == '1') {
ans += 1;
}
}
return ans;
}
}

取不取当下位置要看取完后是否剩下的M和N都大于等于0. 如果一个小于0就说明不能取. 我之前是直接不管就取, 如果出现M小于等于0或者N小于等于0, 直接返回0. 这是不对的. 因为如果一个是0另一个不是0但仍然可以继续往后取啊, 只要不取含有是0的那一个char的string即可. 如果出现M和N小于0, 那一定是上一步取了个什么后到达了这里, 那么我们返回后它那里还会加个1. 但实际不应该 + 1因为上一步去不了, 那这样我们这一步该返回-1, 这样到上一步再加个1就抵消了. 这样看来逻辑就很混乱.

于是我们取之前先看取后是否M和N都大于等于0.

时间复杂度: O(l * m * n)
空间复杂度: O(l * m * n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] charCount = new int[strs.length][2];
for (int i = 0; i < charCount.length; i++) {
String currString = strs[i];
int ones = countOne(currString);
int zeroes = currString.length() - ones;
charCount[i][0] = zeroes;
charCount[i][1] = ones;
}
int[][] memo = new int[m + 1][n + 1];
for (int i = strs.length - 1; i >= 0; i--) {
for (int j = m; j >= 0; j--) {
for (int k = n; k >= 0; k--) {
int taken = 0;
if (j - charCount[i][0] >= 0 && k - charCount[i][1] >= 0) {
taken = memo[j - charCount[i][0]][k - charCount[i][1]] + 1;
}
int notTaken = memo[j][k];
memo[j][k] = Math.max(taken, notTaken);
}
}
}
return memo[m][n];
}

private int countOne(String s) {
char[] sArray = s.toCharArray();
int ans = 0;
for (char c : sArray) {
if (c == '1') {
ans += 1;
}
}
return ans;
}
}

根据递归写出来的dp. 3D dp但是可以简化为2D的.

时间复杂度不变.
空间复杂度: O(m * n)