48
48
49
49
<!-- 这里可写通用的实现逻辑 -->
50
50
51
- 题目可以转换为 ` 0-1 ` 背包问题,在 k 个字符串中选出一些字符串(每个字符串只能使用一次),并且满足字符串最多包含 m 个 0 和 n 个 1,求满足此条件的字符串的最大长度(字符串个数)。
51
+ ** 方法一:动态规划**
52
+
53
+ 我们定义 $f[ i] [ j ] [ k] $ 表示在前 $i$ 个字符串中,使用 $j$ 个 0 和 $k$ 个 1 的情况下最多可以得到的字符串数量。初始时 $f[ i] [ j ] [ k] =0$,答案为 $f[ sz] [ m ] [ n] $,其中 $sz$ 是数组 $strs$ 的长度。
54
+
55
+ 对于 $f[ i] [ j ] [ k] $,我们有两种决策:
56
+
57
+ - 不选第 $i$ 个字符串,此时 $f[ i] [ j ] [ k] =f[ i-1] [ j ] [ k] $;
58
+ - 选第 $i$ 个字符串,此时 $f[ i] [ j ] [ k] =f[ i-1] [ j-a ] [ k-b] +1$,其中 $a$ 和 $b$ 分别是第 $i$ 个字符串中 $0$ 和 $1$ 的数量。
59
+
60
+ 我们取两种决策中的最大值,即可得到 $f[ i] [ j ] [ k] $ 的值。
61
+
62
+ 最终的答案即为 $f[ sz] [ m ] [ n] $。
63
+
64
+ 时间复杂度 $O(sz \times m \times n)$,空间复杂度 $O(sz \times m \times n)$。其中 $sz$ 是数组 $strs$ 的长度;而 $m$ 和 $n$ 分别是字符串中 $0$ 和 $1$ 的数量上限。
65
+
66
+ 我们注意到 $f[ i] [ j ] [ k] $ 的计算只和 $f[ i-1] [ j ] [ k] $ 以及 $f[ i-1] [ j-a ] [ k-b] $ 有关,因此我们可以去掉第一维,将空间复杂度优化到 $O(m \times n)$。
52
67
53
68
<!-- tabs:start -->
54
69
59
74
``` python
60
75
class Solution :
61
76
def findMaxForm (self , strs : List[str ], m : int , n : int ) -> int :
62
- l = len (strs)
63
- dp = [[[0 ] * (n + 1 ) for i in range (m + 1 )] for j in range (l)]
64
- t = [(s.count(' 0' ), s.count(' 1' )) for s in strs]
65
- n0, n1 = t[0 ]
66
- for j in range (m + 1 ):
67
- for k in range (n + 1 ):
68
- if n0 <= j and n1 <= k:
69
- dp[0 ][j][k] = 1
70
-
71
- for i in range (1 , l):
72
- n0, n1 = t[i]
77
+ sz = len (strs)
78
+ f = [[[0 ] * (n + 1 ) for _ in range (m + 1 )] for _ in range (sz + 1 )]
79
+ for i, s in enumerate (strs, 1 ):
80
+ a, b = s.count(" 0" ), s.count(" 1" )
73
81
for j in range (m + 1 ):
74
82
for k in range (n + 1 ):
75
- dp[i][j][k] = dp[i - 1 ][j][k]
76
- if n0 <= j and n1 <= k:
77
- dp[i][j][k] = max (dp[i][j][k], dp[i - 1 ][j - n0][k - n1] + 1 )
78
-
79
- return dp[- 1 ][- 1 ][- 1 ]
83
+ f[i][j][k] = f[i - 1 ][j][k]
84
+ if j >= a and k >= b:
85
+ f[i][j][k] = max (f[i][j][k], f[i - 1 ][j - a][k - b] + 1 )
86
+ return f[sz][m][n]
80
87
```
81
88
82
- 空间优化:
83
-
84
89
``` python
85
90
class Solution :
86
91
def findMaxForm (self , strs : List[str ], m : int , n : int ) -> int :
87
- dp = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
88
- t = [(s.count(' 0' ), s.count(' 1' )) for s in strs]
89
- for k in range (len (strs)):
90
- n0, n1 = t[k]
91
- for i in range (m, n0 - 1 , - 1 ):
92
- for j in range (n, n1 - 1 , - 1 ):
93
- dp[i][j] = max (dp[i][j], dp[i - n0][j - n1] + 1 )
94
- return dp[- 1 ][- 1 ]
92
+ f = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
93
+ for s in strs:
94
+ a, b = s.count(" 0" ), s.count(" 1" )
95
+ for i in range (m, a - 1 , - 1 ):
96
+ for j in range (n, b - 1 , - 1 ):
97
+ f[i][j] = max (f[i][j], f[i - a][j - b] + 1 )
98
+ return f[m][n]
95
99
```
96
100
97
101
### ** Java**
@@ -100,24 +104,56 @@ class Solution:
100
104
101
105
``` java
102
106
class Solution {
103
- public : int findMaxForm (vector <string >& strs , int m , int n ) {
104
- vector< vector< int >> dp(m + 1 , vector< int > (n + 1 ));
105
- for (auto s : strs) {
106
- vector< int > t = count(s);
107
- for (int i = m; i >= t[0 ]; -- i)
108
- for (int j = n; j >= t[1 ]; -- j)
109
- dp[i][j] = max(dp[i][j], dp[i - t[0 ]][j - t[1 ]] + 1 );
107
+ public int findMaxForm (String [] strs , int m , int n ) {
108
+ int sz = strs. length;
109
+ int [][][] f = new int [sz + 1 ][m + 1 ][n + 1 ];
110
+ for (int i = 1 ; i <= sz; ++ i) {
111
+ int [] cnt = count(strs[i - 1 ]);
112
+ for (int j = 0 ; j <= m; ++ j) {
113
+ for (int k = 0 ; k <= n; ++ k) {
114
+ f[i][j][k] = f[i - 1 ][j][k];
115
+ if (j >= cnt[0 ] && k >= cnt[1 ]) {
116
+ f[i][j][k] = Math . max(f[i][j][k], f[i - 1 ][j - cnt[0 ]][k - cnt[1 ]] + 1 );
117
+ }
118
+ }
119
+ }
110
120
}
111
- return dp [m][n];
121
+ return f[sz] [m][n];
112
122
}
113
123
114
- vector<int > count (string s ) {
115
- int n0 = 0 ;
116
- for (char c : s)
117
- if (c == ' 0' ) ++ n0;
118
- return {n0, (int ) s. size() - n0};
124
+ private int [] count (String s ) {
125
+ int [] cnt = new int [2 ];
126
+ for (int i = 0 ; i < s. length(); ++ i) {
127
+ ++ cnt[s. charAt(i) - ' 0' ];
128
+ }
129
+ return cnt;
119
130
}
120
- };
131
+ }
132
+ ```
133
+
134
+ ``` java
135
+ class Solution {
136
+ public int findMaxForm (String [] strs , int m , int n ) {
137
+ int [][] f = new int [m + 1 ][n + 1 ];
138
+ for (String s : strs) {
139
+ int [] cnt = count(s);
140
+ for (int i = m; i >= cnt[0 ]; -- i) {
141
+ for (int j = n; j >= cnt[1 ]; -- j) {
142
+ f[i][j] = Math . max(f[i][j], f[i - cnt[0 ]][j - cnt[1 ]] + 1 );
143
+ }
144
+ }
145
+ }
146
+ return f[m][n];
147
+ }
148
+
149
+ private int [] count (String s ) {
150
+ int [] cnt = new int [2 ];
151
+ for (int i = 0 ; i < s. length(); ++ i) {
152
+ ++ cnt[s. charAt(i) - ' 0' ];
153
+ }
154
+ return cnt;
155
+ }
156
+ }
121
157
```
122
158
123
159
### ** C++**
@@ -126,21 +162,50 @@ class Solution {
126
162
class Solution {
127
163
public:
128
164
int findMaxForm(vector<string >& strs, int m, int n) {
129
- vector<vector<int >> dp(m + 1, vector<int >(n + 1));
130
- for (int k = 0; k < strs.size(); ++k) {
131
- vector<int > t = count(strs[ k] );
132
- for (int i = m; i >= t[ 0] ; --i)
133
- for (int j = n; j >= t[ 1] ; --j)
134
- dp[ i] [ j ] = max(dp[ i] [ j ] , dp[ i - t[ 0]] [ j - t[ 1]] + 1);
165
+ int sz = strs.size();
166
+ int f[ sz + 1] [ m + 1 ] [ n + 1] ;
167
+ memset(f, 0, sizeof(f));
168
+ for (int i = 1; i <= sz; ++i) {
169
+ auto [ a, b] = count(strs[ i - 1] );
170
+ for (int j = 0; j <= m; ++j) {
171
+ for (int k = 0; k <= n; ++k) {
172
+ f[ i] [ j ] [ k] = f[ i - 1] [ j ] [ k] ;
173
+ if (j >= a && k >= b) {
174
+ f[ i] [ j ] [ k] = max(f[ i] [ j ] [ k] , f[ i - 1] [ j - a ] [ k - b] + 1);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ return f[ sz] [ m ] [ n] ;
180
+ }
181
+
182
+ pair<int, int> count(string& s) {
183
+ int a = count_if(s.begin(), s.end(), [](char c) { return c == '0'; });
184
+ return {a, s.size() - a};
185
+ }
186
+ };
187
+ ```
188
+
189
+ ``` cpp
190
+ class Solution {
191
+ public:
192
+ int findMaxForm(vector<string >& strs, int m, int n) {
193
+ int f[ m + 1] [ n + 1 ] ;
194
+ memset(f, 0, sizeof(f));
195
+ for (auto& s : strs) {
196
+ auto [ a, b] = count(s);
197
+ for (int i = m; i >= a; --i) {
198
+ for (int j = n; j >= b; --j) {
199
+ f[ i] [ j ] = max(f[ i] [ j ] , f[ i - a] [ j - b ] + 1);
200
+ }
201
+ }
135
202
}
136
- return dp [ m] [ n ] ;
203
+ return f [ m] [ n ] ;
137
204
}
138
205
139
- vector<int> count(string s) {
140
- int n0 = 0;
141
- for (char c : s)
142
- if (c == '0') ++n0;
143
- return {n0, (int) s.size() - n0};
206
+ pair<int, int> count(string& s) {
207
+ int a = count_if(s.begin(), s.end(), [](char c) { return c == '0'; });
208
+ return {a, s.size() - a};
144
209
}
145
210
};
146
211
```
@@ -149,29 +214,61 @@ public:
149
214
150
215
``` go
151
216
func findMaxForm (strs []string , m int , n int ) int {
152
- dp := make ([][]int , m+1 )
153
- for i := 0 ; i < m+1 ; i++ {
154
- dp[i] = make ([]int , n+1 )
217
+ sz := len (strs)
218
+ f := make ([][][]int , sz+1 )
219
+ for i := range f {
220
+ f[i] = make ([][]int , m+1 )
221
+ for j := range f[i] {
222
+ f[i][j] = make ([]int , n+1 )
223
+ }
155
224
}
156
- for _ , s := range strs {
157
- t := count (s)
158
- for i := m; i >= t[0 ]; i-- {
159
- for j := n; j >= t[1 ]; j-- {
160
- dp[i][j] = max (dp[i][j], dp[i-t[0 ]][j-t[1 ]]+1 )
225
+ for i := 1 ; i <= sz; i++ {
226
+ a , b := count (strs[i-1 ])
227
+ for j := 0 ; j <= m; j++ {
228
+ for k := 0 ; k <= n; k++ {
229
+ f[i][j][k] = f[i-1 ][j][k]
230
+ if j >= a && k >= b {
231
+ f[i][j][k] = max (f[i][j][k], f[i-1 ][j-a][k-b]+1 )
232
+ }
161
233
}
162
234
}
163
235
}
164
- return dp[m][n]
236
+ return f[sz][m][n]
237
+ }
238
+
239
+ func count (s string ) (int , int ) {
240
+ a := strings.Count (s, " 0" )
241
+ return a, len (s) - a
242
+ }
243
+
244
+ func max (a , b int ) int {
245
+ if a > b {
246
+ return a
247
+ }
248
+ return b
165
249
}
250
+ ```
166
251
167
- func count (s string ) []int {
168
- n0 := 0
169
- for i := 0 ; i < len (s); i++ {
170
- if s[i] == ' 0' {
171
- n0++
252
+ ``` go
253
+ func findMaxForm (strs []string , m int , n int ) int {
254
+ f := make ([][]int , m+1 )
255
+ for i := range f {
256
+ f[i] = make ([]int , n+1 )
257
+ }
258
+ for _ , s := range strs {
259
+ a , b := count (s)
260
+ for j := m; j >= a; j-- {
261
+ for k := n; k >= b; k-- {
262
+ f[j][k] = max (f[j][k], f[j-a][k-b]+1 )
263
+ }
172
264
}
173
265
}
174
- return []int {n0, len (s) - n0}
266
+ return f[m][n]
267
+ }
268
+
269
+ func count (s string ) (int , int ) {
270
+ a := strings.Count (s, " 0" )
271
+ return a, len (s) - a
175
272
}
176
273
177
274
func max (a , b int ) int {
@@ -182,6 +279,58 @@ func max(a, b int) int {
182
279
}
183
280
```
184
281
282
+ ### ** TypeScript**
283
+
284
+ ``` ts
285
+ function findMaxForm(strs : string [], m : number , n : number ): number {
286
+ const sz = strs .length ;
287
+ const f = Array .from ({ length: sz + 1 }, () =>
288
+ Array .from ({ length: m + 1 }, () => Array .from ({ length: n + 1 }, () => 0 )),
289
+ );
290
+ const count = (s : string ): [number , number ] => {
291
+ let a = 0 ;
292
+ for (const c of s ) {
293
+ a += c === ' 0' ? 1 : 0 ;
294
+ }
295
+ return [a , s .length - a ];
296
+ };
297
+ for (let i = 1 ; i <= sz ; ++ i ) {
298
+ const [a, b] = count (strs [i - 1 ]);
299
+ for (let j = 0 ; j <= m ; ++ j ) {
300
+ for (let k = 0 ; k <= n ; ++ k ) {
301
+ f [i ][j ][k ] = f [i - 1 ][j ][k ];
302
+ if (j >= a && k >= b ) {
303
+ f [i ][j ][k ] = Math .max (f [i ][j ][k ], f [i - 1 ][j - a ][k - b ] + 1 );
304
+ }
305
+ }
306
+ }
307
+ }
308
+ return f [sz ][m ][n ];
309
+ }
310
+ ```
311
+
312
+ ``` ts
313
+ function findMaxForm(strs : string [], m : number , n : number ): number {
314
+ const f = Array .from ({ length: m + 1 }, () => Array .from ({ length: n + 1 }, () => 0 ));
315
+ const count = (s : string ): [number , number ] => {
316
+ let a = 0 ;
317
+ for (const c of s ) {
318
+ a += c === ' 0' ? 1 : 0 ;
319
+ }
320
+ return [a , s .length - a ];
321
+ };
322
+ for (const s of strs ) {
323
+ const [a, b] = count (s );
324
+ for (let i = m ; i >= a ; -- i ) {
325
+ for (let j = n ; j >= b ; -- j ) {
326
+ f [i ][j ] = Math .max (f [i ][j ], f [i - a ][j - b ] + 1 );
327
+ }
328
+ }
329
+ }
330
+ return f [m ][n ];
331
+ }
332
+ ```
333
+
185
334
### ** ...**
186
335
187
336
```
0 commit comments