Leetcode 886、可能的二分法
DFS
思路
- 使用颜色标识当前节点的状态, R 表示红色; B 表示蓝色; W 表示白色,即初始状态
- 使用一个状态数组 status 来标识当前节点的颜色
- 根据 dislike 数组构建邻接表 graph
- dfs 方法里面,判断 pre 的值, currStatus 是 pre 的相反值,遍历当前节点的邻接链表:
- 如果当前位置已经访问过了,如果颜色和 pre 一样,直接返回 false, 表示不可以进行二分;
- 如果是 W ,说明没有被访问过,那么就把当前位置的状态设置为 currStatus
- 最后返回结果
时间复杂度
- O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小
空间复杂度
- O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小
代码
public class PossibleBipartition {
/**
* 思路:DFS
* 使用颜色标识当前节点的状态, R 表示红色; B 表示蓝色; W 表示白色,即初始状态
* 使用一个状态数组 status 来标识当前节点的颜色
* 根据 dislike 数组构建邻接表 graph
* dfs 方法里面,判断 pre 的值, currStatus 是 pre 的相反值,遍历当前节点的邻接链表:
* 如果当前位置已经访问过了,如果颜色和 pre 一样,直接返回 false, 表示不可以进行二分;
* 如果是 W ,说明没有被访问过,那么就把当前位置的状态设置为 currStatus,
* 最后返回结果
*
* 时间复杂度:O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小。
* 空间复杂度:O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小。
*
* @param n
* @param dislikes
*/
public boolean possibleBipartition(int n, int[][] dislikes) {
List<List<Integer>> graph = new ArrayList<>();
for(int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
for(int i = 0; i < dislikes.length; i++) {
graph.get(dislikes[i][0] - 1).add(dislikes[i][1] - 1);
graph.get(dislikes[i][1] - 1).add(dislikes[i][0] - 1);
}
String[] status = new String[n];
Arrays.fill(status, "W"); // R 表示红色, B 表示蓝色, W 表示白色,是初始状态
for(int i = 0; i < graph.size(); i++) {
if(status[i].equals("W")) {
status[i] = "R";
if(!dfs(status, graph, i, "R")) {
return false;
}
}
}
return true;
}
public boolean dfs(String[] status, List<List<Integer>> graph, int index, String pre) {
String currStatus = "";
if(pre.equals("R")) {
currStatus = "B";
}else {
currStatus = "R";
}
List<Integer> curr = graph.get(index);
for(int i = 0; i < curr.size(); i++) {
if(status[curr.get(i)].equals("W")) {
status[curr.get(i)] = currStatus;
if(!dfs(status, graph, curr.get(i), currStatus)) return false;
}else if(status[curr.get(i)].equals(pre)) {
return false;
}
}
return true;
}
}