lihe / Leetcode

Record the process of Leetcode by GitHub

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode_785_Is Graph Bipartite?

lihe opened this issue · comments

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].

解题思路:深度优先着色;使用数组记录每个节点的颜色,颜色可以是0,1,-1(未着色);遍历每个节点,对每个未着色的节点着色,从该节点进行深度优先搜索着色,每个邻接点与当前节点着相反的颜色,如果当邻节点已经着色,且颜色与当前节点相同,那么不是二分图。

class Solution {
    public boolean isBipartite(int[][] graph) {
        int n = graph.length;
        int[] color = new int[n];

        Arrays.fill(color, -1);

        for(int start = 0; start < n; start++){
            if(color[start] == -1){
                Stack<Integer> stack = new Stack<>();

                stack.push(start);
                color[start] = 0;

                while (!stack.empty()){
                    Integer node = stack.pop();

                    for(int neigh: graph[node]){
                        if(color[neigh] == -1){
                            stack.push(neigh);
                            color[neigh] = color[node] ^ 1;
                        }
                        else if(color[neigh] == color[node])
                            return false;
                    }
                }
            }
        }

        return true;
    }
}
class Solution { 
	public boolean isBipartite(int[][] graph) {
        if (graph == null || graph.length == 0) return false;
        int v = graph.length;
        int[] colors = new int[v];  // 0未被染色, 1黑  2白
        // 要考虑非连通图, 所以要遍历每一个结点
        for (int i = 0; i < v; i++) {
            // lastColor为0
            if (!dfs(graph, i, colors, 0)) return false;
        }
        return true;
    }
    private boolean dfs(int[][] graph, int i, int[] colors, int lastColor) {
        // 注意,被染色的就不要继续染色了(因为这是自底向上的,被染色的点,其相连的节点肯定被染色了)
        // 如果继续对被染色的节点染色,就会导致死循环
        if (colors[i] != 0) return colors[i] != lastColor;
        // 未被染色,染成与相邻结点不同的颜色(lastColor为0时,就染成1)
        colors[i] = lastColor == 1 ? 2 : 1;
        for (int j = 0; j < graph[i].length; j++) {
            if (!dfs(graph, graph[i][j], colors, colors[i])) return false;
        }
        return true;
    }
}