原题链接:
https://leetcode.cn/problems/possible-bipartition/description/
完成情况:
解题思路:
这段代码是一个解决可能的二分图问题的Java类。在该类中,首先创建了一个Solution类,其中包含了两个方法:possibleBipartition和dfs。
-
possibleBipartition方法接受两个参数,一个是整数n,表示节点数量,另一个是二维数组dislikes,表示节点之间的不喜欢关系。在该方法中,首先创建了一个长度为n+1的整型数组color,用于标记节点的颜色,以及一个长度为n+1的List数组g,用于表示图的邻接表。然后,遍历dislikes数组,将不喜欢关系添加到邻接表中。接着,对每个节点进行深度优先搜索(dfs),如果发现有节点与相邻节点颜色相同,则返回false,表示无法进行二分。最后,如果所有节点都能够满足二分条件,则返回true。
-
dfs方法用于进行深度优先搜索,接受四个参数:当前节点curnode、当前颜色nowcolor、颜色数组color和邻接表数组g。在该方法中,首先将当前节点标记为当前颜色,然后遍历当前节点的相邻节点,如果发现相邻节点与当前节点颜色相同,则返回false,表示无法进行二分。如果相邻节点未被标记颜色,则递归调用dfs方法,并将颜色取反后的值传入,直到遍历完所有与当前节点相邻的节点。如果所有相邻节点都能够满足二分条件,则返回true。
总的来说,这段代码利用深度优先搜索算法判断是否可以将节点划分为两个不相交的子集,使得同一个子集内的节点之间没有不喜欢关系。
参考代码:
_886可能的二分法__dfs
package leetcode板块;
import java.util.ArrayList;
import java.util.List;
public class _886可能的二分法__dfs {
/**
*
* @param n : 表示有 n 个人,编号为 1~n
* @param dislikes : 表示这两个人不能处于同一个分组中 【二维dp】
* @return 问: 当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。
*/
public boolean possibleBipartition(int n, int[][] dislikes) {
// TODO 能否将所有人分成两组数
// dfs每一个数,并且对这其中的每一个数都设置一个标记,
// 如果当前不存在标记那么随便设置,如果当前存在标记,那么另一个必须满足能取得相反的标记,否则就认为错误
int [] color = new int [n + 1]; //默认是0
List<Integer> [] g_near = new List [n+1]; //记录当前图的邻接情况
for (int i = 0; i <= n;++i){
g_near[i] = new ArrayList<>();
}
for (int [] dislike :dislikes){
//在每一个节点的图表中,记录下无法共存的节点
g_near[dislike[0]].add(dislike[1]);
g_near[dislike[1]].add(dislike[0]);
}
//--------------------------------------------------------------
// TODO 每个节点去进行判断,看看是否存在无法共存的节点情况
for (int i = 1;i<=n;++i){
if (color[i] == 0 && !dfs_possibleBipartition(i,1,color,g_near)) return false;
}
return true;
}
/**
*
* @param curNode 当前节点curnode
* @param curNodeColor 当前颜色nowcolor
* @param color 颜色数组color
* @param g_near 邻接表数组g
* @return
*/
private boolean dfs_possibleBipartition(int curNode, int curNodeColor, int[] color, List<Integer>[] g_near) {
color[curNode] = curNodeColor;
for (int gNode : g_near[curNode]){ //每个表节点去遍历其对应邻近表里面的gNode
if (color[gNode] != 0 && color[gNode] == color[curNode]){ //如果节点内的gNode与color[curNode]相等,则说明冲突
return false;
}
if (color[gNode] == 0 && !dfs_possibleBipartition(gNode,3 ^ curNodeColor,color,g_near)){ //3 ^ nowcolor: 这个表达式涉及到位运算。
return false;
}
}
return true;
}
}
_886可能的二分法__bfs
package leetcode板块;
import java.util.*;
public class _886可能的二分法__bfs {
/**
*
* @param n
* @param dislikes
* @return
*/
public boolean possibleBipartition(int n, int[][] dislikes) {
int [] color = new int [n + 1]; //默认是0,
// 这里3^nowcolor进行染色分组,0表示未分组,1表示分组1,2表示分组2
// 在进行使用时,采用异或, 3(11)异或1(01)得到2(10),3(11)异或2(10)得到1(01)
List<Integer> [] g_near = new List [n+1]; //记录当前图的邻接情况
for (int i = 0; i <= n;++i){
g_near[i] = new ArrayList<>();
}
for (int [] dislike :dislikes){
//在每一个节点的图表中,记录下无法共存的节点
g_near[dislike[0]].add(dislike[1]);
g_near[dislike[1]].add(dislike[0]);
}
//--------------------------------------------------------------
// TODO 每个节点去进行判断,看看是否存在无法共存的节点情况
for (int i = 1;i<=n;++i){
if (color[i] == 0){
Deque<Integer> myQueue = new ArrayDeque<Integer>();
myQueue.offer(i);
color[i] = 1; //初始化,第一个就假设染" 1 "
while (!myQueue.isEmpty()){
int curNode = myQueue.poll();
for (int g_nearNode : g_near[curNode]){ //遍历当前结点的List
if (color[g_nearNode] > 0 && color[g_nearNode] == color[curNode]){
return false;
}
if (color[g_nearNode] == 0){
color[g_nearNode] = 3 ^ color[curNode];
myQueue.offer(g_nearNode);
}
}
}
}
}
return true;
}
}