• [LeetCode] 785. Is Graph Bipartite?


    Given an undirected graph, return true if and only if it is bipartite.

    Recall that a graph is bipartite if we can split it's set of nodes into two independent subsets A and B such that every edge in the graph has one node in A and another node in B.

    The graph is given in the following form: graph[i] is a list of indexes j for which the edge between nodes i and j exists.  Each node is an integer between 0 and graph.length - 1.  There are no self edges or parallel edges: graph[i] does not contain i, and it doesn't contain any element twice.

    Example 1:
    Input: [[1,3], [0,2], [1,3], [0,2]]
    Output: true
    Explanation: 
    The graph looks like this:
    0----1
    |    |
    |    |
    3----2
    We can divide the vertices into two groups: {0, 2} and {1, 3}.
    
    Example 2:
    Input: [[1,2,3], [0,2], [0,1,3], [0,2]]
    Output: false
    Explanation: 
    The graph looks like this:
    0----1
    |   |
    |   |
    3----2
    We cannot find a way to divide the set of nodes into two independent subsets.

    Note:

    • graph will have length in range [1, 100].
    • graph[i] will contain integers in range [0, graph.length - 1].
    • graph[i] will not contain i or duplicate values.
    • The graph is undirected: if any element j is in graph[i], then i will be in graph[j].

    判断二分图。

    给定一个无向图graph,当这个图为二分图时返回true。

    如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。

    graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/is-graph-bipartite
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    我这里提供两种做法,其实都是涂色法,只是涂色的方式不同。首先是BFS。可以参考这个油管视频,深刻理解涂色法。大致的思路是,当你遍历graph里面的节点的时候,当遇到某一个节点,如果他没有被染色,你就试图给他染成某一种颜色,但是对于这个点的所有邻居节点,需要给他们染成一个别的颜色以区分开。照着这个思路,你需要确保邻居节点被染成不同的颜色。如果遍历结束,所有节点都被染色成功,则说明是一个二分图;如果在染色过程中发现有节点已经被染色但是染色错误,则这个图不是二分图。既然是BFS,就会需要一个queue来遍历图的每一个节点。其他部分请参见代码。我这里给的染色是1和2,代表两种不同的颜色,如果遇到某个节点与其邻居节点颜色一样则返回false。

    时间O(V + E)

    空间O(n)

    Java实现

     1 class Solution {
     2     public boolean isBipartite(int[][] graph) {
     3         //BFS
     4         // 0(not meet), 1(black), 2(white)
     5         int[] visited = new int[graph.length];
     6         for (int i = 0; i < graph.length; i++) {
     7             if (graph[i].length != 0 && visited[i] == 0) {
     8                 visited[i] = 1;
     9                 Queue<Integer> q = new LinkedList<>();
    10                 q.offer(i);
    11                 while (!q.isEmpty()) {
    12                     int current = q.poll();
    13                     for (int c : graph[current]) {
    14                         if (visited[c] == 0) {
    15                             visited[c] = (visited[current] == 1) ? 2 : 1;
    16                             q.offer(c);
    17                         } else {
    18                             if (visited[c] == visited[current]) {
    19                                 return false;
    20                             }
    21                         }
    22                     }
    23                 }
    24             }
    25         }
    26         return true;
    27     }
    28 }

    JavaScript实现

     1 /**
     2  * @param {number[][]} graph
     3  * @return {boolean}
     4  */
     5 var isBipartite = function (graph) {
     6     let visited = new Array(graph.length).fill(0);
     7     for (let i = 0; i < graph.length; i++) {
     8         if (graph[i].length && visited[i] == 0) {
     9             visited[i] = 1;
    10             let queue = [];
    11             queue.push(i);
    12             while (queue.length) {
    13                 let cur = queue.shift();
    14                 for (let next of graph[cur]) {
    15                     if (visited[next] == 0) {
    16                         visited[next] = visited[cur] == 1 ? 2 : 1;
    17                         queue.push(next);
    18                     } else {
    19                         if (visited[cur] === visited[next]) {
    20                             return false;
    21                         }
    22                     }
    23                 }
    24             }
    25         }
    26     }
    27     return true;
    28 };

    DFS思路跟BFS几乎没什么两样,无非是DFS往下层寻找的时候,涂色是按一正一负这样涂的,而BFS是涂成1或2。

    时间O(V + E)

    空间O(n)

    Java实现

     1 class Solution {
     2     public boolean isBipartite(int[][] graph) {
     3         int[] visited = new int[graph.length];
     4         for (int i = 0; i < graph.length; i++) {
     5             // 当前点没有被访问过且染色失败,返回false
     6             if (visited[i] == 0 && !dfs(graph, visited, 1, i)) {
     7                 return false;
     8             }
     9         }
    10         return true;
    11     }
    12 
    13     /**
    14      * @param graph   图
    15      * @param node    当前处理的顶点
    16      * @param color   当前顶点即将被染的颜色
    17      * @param visited 记录顶点是否被访问过
    18      * @return 成功染色,返回true,失败染色返回false
    19      */
    20     private boolean dfs(int[][] graph, int[] visited, int color, int node) {
    21         if (visited[node] != 0) {
    22             return visited[node] == color;
    23         } else {
    24             visited[node] = color;
    25             for (int nei : graph[node]) {
    26                 if (!dfs(graph, visited, -color, nei)) {
    27                     return false;
    28                 }
    29             }
    30         }
    31         return true;
    32     }
    33 }

    相关题目

    785. Is Graph Bipartite

    886. Possible Bipartition

    LeetCode 题目总结

  • 相关阅读:
    第02周学习提升建议:【python安装、变量、输入输出、流程、循环】--【第五篇】流程、循环
    向gitlab上传本地项目
    [jenkins+gitlab+postman] 持续集成
    linux 上安装newman
    【python】读取cfg/ini/txt配置文件
    【CI/CD】docker部署gitlab,并且本地拉取gitlab代码成功
    【CI/CD】docker部署Jenkins
    【TCP知识】03_Linux查看TCP连接状态
    【nginx知识】02_【转载】nginx反向代理时保持长连接
    【TCP/IP知识】02_【转载】TCP 半连接队列和全连接队列
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13316312.html
Copyright © 2020-2023  润新知