Merge pull request #2847 from HelloDam/master

添加474. 一和零 java 三维DP数组实现代码
This commit is contained in:
程序员Carl
2025-03-05 11:56:57 +08:00
committed by GitHub
2 changed files with 139 additions and 1 deletions

View File

@ -261,8 +261,70 @@ public:
## 其他语言版本
### Java
三维DP数组实现
```java
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
/// 数组有三个维度
// 第一个维度:取前面的几个字符串
// 第二个维度0的数量限制背包维度 1 容量)
// 第三个维度1的数量限制背包维度 2 容量)
int[][][] dpArr = new int[strs.length][m + 1][n + 1];
/// 初始化dpArr数组
// 计算第一个字符串的零数量和1数量
int zeroNum = 0;
int oneNum = 0;
for (char c : strs[0].toCharArray()) {
if (c == '0') {
zeroNum++;
} else {
oneNum++;
}
}
// 当0数量、1数量都容得下第一个字符串时将DP数组的相应位置初始化为1因为当前的子集数量为1
for (int j = zeroNum; j <= m; j++) {
for (int k = oneNum; k <= n; k++) {
dpArr[0][j][k] = 1;
}
}
/// 依次填充加入第i个字符串之后的DP数组
for (int i = 1; i < strs.length; i++) {
zeroNum = 0;
oneNum = 0;
for (char c : strs[i].toCharArray()) {
if (c == '0') {
zeroNum++;
} else {
oneNum++;
}
}
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
if (j >= zeroNum && k >= oneNum) {
// --if-- 当0数量维度和1数量维度的容量都大于等于当前字符串的0数量和1数量时才考虑是否将当前字符串放入背包
// 不放入第i个字符串子集数量仍为 dpArr[i - 1][j][k]
// 放入第i个字符串需要在0维度腾出 zeroNum 个容量1维度腾出 oneNum 个容量,然后放入当前字符串,即 dpArr[i - 1][j - zeroNum][k - oneNum] + 1)
dpArr[i][j][k] = Math.max(dpArr[i - 1][j][k], dpArr[i - 1][j - zeroNum][k - oneNum] + 1);
} else {
// --if-- 无法放入第i个字符串子集数量仍为 dpArr[i - 1][j][k]
dpArr[i][j][k] = dpArr[i - 1][j][k];
}
}
}
}
return dpArr[dpArr.length - 1][m][n];
}
}
```
二维DP数组实现
```Java
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
@ -682,3 +744,4 @@ public class Solution
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@ -176,6 +176,81 @@ int main() {
### Java
```java
import java.util.Scanner;
public class Main {
private static int[] father;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int pointNum = scanner.nextInt();
father = new int[pointNum + 1];
init();
for (int i = 0; i < pointNum; i++) {
join(scanner.nextInt(), scanner.nextInt());
}
}
/**
* 并查集初始化
*/
private static void init() {
for (int i = 1; i < father.length; i++) {
// 让每个元素指向自己
father[i] = i;
}
}
/**
* 并查集寻根
*
* @param u
* @return
*/
private static int find(int u) {
// 判断 u 是否等于自己,如果是的话,直接返回自己
// 如果不等于自己,就寻找根,寻找的时候,反复进行路径压缩
return u == father[u] ? u : (father[u] = find(father[u]));
}
/**
* 判断 u 和 v 是否同根
*
* @param u
* @param v
* @return
*/
private static boolean isSame(int u, int v) {
return find(u) == find(v);
}
/**
* 添加 边 到并查集v 指向 u
*
* @param u
* @param v
*/
private static void join(int u, int v) {
// --if-- 如果两个点已经同根,说明他们的信息已经存储到并查集中了,直接返回即可
// 寻找u的根
int uRoot = find(u);
// 寻找v的根
int vRoot = find(v);
if (uRoot == vRoot) {
// --if-- 如果u,v的根相同说明两者已经连接了直接输出
System.out.println(u + " " + v);
return;
}
// --if-- 将信息添加到并查集
father[vRoot] = uRoot;
}
}
```
### Python
```python