【Garen刷题笔记】LeetCode 785.判断二分图

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

思路

判断二分图的思想,就是遍历图+染色法,无向图的遍历可以采用深度优先遍历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),遍历每一个点,直至所有点被染色,遍历每一条边判断邻接关系,其中 N N N M M M 分别是无向图中的点数和边数。

空间复杂度: O ( N ) O(N) O(N),存储节点颜色的数组需要 O ( N ) O(N) O(N) 的空间,并且在广度优先搜索中维护一个队列,队列中最多有 N − 1 N-1 N1 个节点,所以需要 O ( N ) O(N) O(N) 的空间。如果这里采用深度优先搜索遍历,则需要进行递归或维护一个栈,栈的最大深度为 N N N,空间复杂度仍是 O ( N ) O(N) O(N)

你可能感兴趣的:(LeetCode刷题笔记,算法,数据结构,java,leetcode)