可能的二分法
难度:
标签:
题目描述
代码结果
运行时间: 72 ms, 内存: 21.7 MB
/*
思路:
使用 Java Stream API 解决该问题,我们仍然遵循二分图检测的思路。
具体步骤:
1. 构建图的数据结构,这里我们使用 Map<Integer, List<Integer>> 来表示邻接表。
2. 使用 Stream API 进行图的构建和处理。
3. 使用递归的方式实现 DFS 并检查冲突。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public boolean possibleBipartition(int n, int[][] dislikes) {
Map<Integer, List<Integer>> graph = IntStream.rangeClosed(1, n)
.boxed()
.collect(Collectors.toMap(i -> i, i -> new ArrayList<>()));
Arrays.stream(dislikes).forEach(dislike -> {
graph.get(dislike[0]).add(dislike[1]);
graph.get(dislike[1]).add(dislike[0]);
});
int[] color = new int[n + 1];
for (int i = 1; i <= n; i++) {
if (color[i] == 0 && !dfs(graph, color, i, 1)) {
return false;
}
}
return true;
}
private boolean dfs(Map<Integer, List<Integer>> graph, int[] color, int node, int c) {
color[node] = c;
for (int neighbor : graph.get(node)) {
if (color[neighbor] == 0) {
if (!dfs(graph, color, neighbor, -c)) {
return false;
}
} else if (color[neighbor] == c) {
return false;
}
}
return true;
}
}
解释
方法:
该题解采用了图的深度优先搜索(DFS)算法来解决问题。首先,将给定的不喜欢关系转化为一个图的邻接表表示,其中每个节点代表一个人,每条边代表两个人之间的不喜欢关系。然后,尝试将图分为两个不相交的子集(即两个组),使得每个组内的人都不互相不喜欢。为此,我们使用DFS遍历图,同时用两个数组 'left' 和 'right' 分别记录每个人是否属于左组或右组。在遍历过程中,如果遇到一个已经访问过的节点,我们检查它是否已经被分配到了正确的组中;如果遇到一个未访问过的节点,我们将其分配到当前组的对立组中,并继续DFS遍历其邻居。如果在任何时候,我们发现无法将一个节点分配到一个组中而不违反不喜欢关系,我们返回 false。如果整个图都被成功地遍历并分组,我们返回 true。
时间复杂度:
O(V + E) 或 O(n + dislikes.length)
空间复杂度:
O(V + E) 或 O(n + dislikes.length)
代码细节讲解
🦆
在DFS中,你是如何决定将节点分配到左组还是右组的?这种决定有没有特定的规则或条件?
▷🦆
题解中提到,如果在遍历过程中遇到已经访问过的节点,需要检查它是否已经被分配到了正确的组中。这里的‘正确的组’是指什么?如何定义这个正确性?
▷🦆
如果在DFS过程中发现一个节点无法被分配到任何一个组中而不违反不喜欢关系,算法会返回false。能否具体解释这种情况是如何检测出来的?
▷