LeetCode 785.判断二分图(7.16日题)
题目:给定一个无向图graph,当这个图为二分图时返回true。
如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。

思路
判断二分图的思想,就是遍历图+染色法,无向图的遍历可以采用深度优先遍历DFS和广度优先遍历BFS。染色法的算法流程如下:
- 我们任选一个节点开始,将其染成红色,并从该节点开始对整个无向图进行遍历; 在遍历的过程中,如果我们通过节点 u 遍历到了节点 v(即 u 和 v 在图中有一条边直接相连),那么会有两种情况:
- 如果 v 未被染色,那么我们将其染成与 u 不同的颜色,并对 v 直接相连的节点进行遍历;
- 如果 v 被染色,并且颜色与 u 相同,那么说明给定的无向图不是二分图。我们可以直接退出遍历并返回 False 作为答案。
- 当遍历结束时,说明给定的无向图是二分图,返回 True 作为答案。
注意:因题目未规定图一定为连通图,所以要遍历确保每一个节点被染色。
代码
class Solution {
public boolean isBipartite(int[][] graph) {
//BFS
Queue<Integer> queue = new LinkedList<>();
int n = graph.length;
int[] color = new int[n];
//图不一定联通,所以遍历
for(int i = 0; i < n; ++i){
if(color[i] == 0){
queue.add(i);
color[i] = 1;
while(!queue.isEmpty()){
int node = queue.poll();
//遍历出队元素邻接点
for(int neighbor : graph[node]){
if(color[neighbor] == 0){
queue.add(neighbor);
color[neighbor] = color[node] == 1 ? 2 : 1;
}
if(color[neighbor] == color[node]){
return false;
}
}
}
}
}
return true;
}
}
复杂度分析
时间复杂度:O(N+M)O(N+M)O(N+M),遍历每一个点,直至所有点被染色,遍历每一条边判断邻接关系,其中 NNN 和 MMM 分别是无向图中的点数和边数。
空间复杂度:O(N)O(N)O(N),存储节点颜色的数组需要 O(N)O(N)O(N) 的空间,并且在广度优先搜索中维护一个队列,队列中最多有 N−1N-1N−1 个节点,所以需要 O(N)O(N)O(N) 的空间。如果这里采用深度优先搜索遍历,则需要进行递归或维护一个栈,栈的最大深度为NNN,空间复杂度仍是O(N)O(N)O(N)。
这篇博客详细介绍了如何解决LeetCode 785题——判断二分图。通过深度优先遍历(DFS)或广度优先遍历(BFS)结合染色法来判断图是否为二分图。在遍历过程中,遇到相邻节点颜色相同则返回False,否则给相邻节点染上不同颜色。遍历结束后,若所有节点都被染色,则图是二分图,返回True。注意要处理非连通图的情况。最后,分析了算法的时间复杂度为O(N+M)和空间复杂度为O(N)。
2924

被折叠的 条评论
为什么被折叠?



