Skip to content

Commit ad1d866

Browse files
committed
二刷474
1 parent 427e872 commit ad1d866

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

Diff for: docs/0474-ones-and-zeroes.adoc

+12-13
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
https://leetcode.cn/problems/ones-and-zeroes/[LeetCode - 474. 一和零 ^]
55

6-
给你一个二进制字符串数组 `+strs+` 和两个整数 `+m+``+n+`
6+
给你一个二进制字符串数组 `strs` 和两个整数 `m``n`
77

8-
请你找出并返回 `+strs+` 的最大子集的长度,该子集中 *最多*`+m+``+0+``+n+``+1+`
8+
请你找出并返回 `strs` 的最大子集的长度,该子集中 *最多*`m``0``n``1`
99

10-
如果 `+x+` 的所有元素也是 `+y+` 的元素,集合 `+x+` 是集合 `+y+`*子集*
10+
如果 `x` 的所有元素也是 `y` 的元素,集合 `x` 是集合 `y`*子集*
1111

1212
*示例 1:*
1313

@@ -31,11 +31,10 @@ https://leetcode.cn/problems/ones-and-zeroes/[LeetCode - 474. 一和零 ^]
3131

3232
* `+1 <= strs.length <= 600+`
3333
* `+1 <= strs[i].length <= 100+`
34-
* `+strs[i]+` 仅由 `+'0'+``+'1'+` 组成
34+
* `strs[i]` 仅由 `0``1` 组成
3535
* `+1 <= m, n <= 100+`
3636
3737
38-
3938
== 思路分析
4039

4140
思路:把总共的 0 和 1 的个数视为背包的容量,每一个字符串视为装进背包的物品。这道题就可以使用 0-1 背包问题的思路完成,这里的目标值是能放进背包的字符串的数量。
@@ -58,14 +57,14 @@ include::{sourcedir}/_0474_OnesAndZeroes.java[tag=answer]
5857
----
5958
--
6059
61-
// 二刷::
62-
// +
63-
// --
64-
// [{java_src_attr}]
65-
// ----
66-
// include::{sourcedir}/_0474_OnesAndZeroes_2.java[tag=answer]
67-
// ----
68-
// --
60+
二刷::
61+
+
62+
--
63+
[{java_src_attr}]
64+
----
65+
include::{sourcedir}/_0474_OnesAndZeroes_2.java[tag=answer]
66+
----
67+
--
6968
====
7069

7170

Diff for: logbook/202503.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ endif::[]
195195
|{doc_base_url}/0148-sort-list.adoc[题解]
196196
|✅ 分治
197197

198+
|{counter:codes2503}
199+
|{leetcode_base_url}/ones-and-zeroes/[474. 一和零^]
200+
|{doc_base_url}/0474-ones-and-zeroes.adoc[题解]
201+
|❌ 动态规划,多维度“物品”就无从下手,还要多练。
202+
198203
|===
199204

200205
截止目前,本轮练习一共完成 {codes2503} 道题。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.diguage.algo.leetcode;
2+
3+
public class _0474_OnesAndZeroes_2 {
4+
// tag::answer[]
5+
/**
6+
* @author D瓜哥 · https://www.diguage.com
7+
* @since 2025-04-08 20:44:04
8+
*/
9+
public int findMaxForm(String[] strs, int m, int n) {
10+
// 计算每个字符串中 0 和 1 的数量
11+
int length = strs.length;
12+
int[][] bits = new int[length][2];
13+
for (int i = 0; i < length; i++) {
14+
for (char c : strs[i].toCharArray()) {
15+
bits[i][c - '0']++;
16+
}
17+
}
18+
// 1、确定 dp 数组(dp table)以及下标的含义
19+
// ① 表示此时处理的字符串
20+
// ② 表示此时 0 的个数,即 0 的数量限制
21+
// ③ 表示此时 1 的个数,即 1 的数量限制
22+
// (x, y, z) 指的是到达第 x 个字符串时,
23+
// 如果有 y 个 0 和 z 个 1,那么最大子集数量
24+
// 3、dp 数组如何初始化
25+
// 由于不能为负数,最初都没有选择,则全部初始化为 0
26+
int[][][] dp = new int[length + 1][m + 1][n + 1];
27+
// 4、确定遍历顺序
28+
// 从第一个字符串开始遍历
29+
for (int x = 1; x <= length; x++) {
30+
int zeros = bits[x - 1][0];
31+
int ones = bits[x - 1][1];
32+
for (int y = 0; y <= m; y++) {
33+
for (int z = 0; z <= n; z++) {
34+
// 2、确定递推公式
35+
// dp[x][y][z] = max(dp[x][y][z], dp[x-1][y - zeros][z - ones] + 1);
36+
if (y >= zeros && z >= ones) {
37+
// 在加入当前字符串和不加入当前字符串中选择其一
38+
dp[x][y][z] = Math.max(dp[x - 1][y][z], dp[x - 1][y - zeros][z - ones] + 1);
39+
} else {
40+
// 0 和 1 的容量不够,无法加入当前字符串,只能从上面继承
41+
dp[x][y][z] = dp[x - 1][y][z];
42+
}
43+
}
44+
}
45+
}
46+
return dp[length][m][n];
47+
}
48+
// end::answer[]
49+
}

0 commit comments

Comments
 (0)