[LeetCode] 785. Is Graph Bipartite?
Given an undirectedgraph
, returntrue
if and only if it is bipartite.
Recall that a graph isbipartiteif we can split it's set of nodes into two independentsubsets 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 indexesj
i
andj
exists. Each node is an integer between0
andgraph.length - 1
. There are no self edges or parallel edges:graph[i]
does not containi
, 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 containi
or duplicate values.- The graph is undirected: if any element
j
is ingraph[i]
, theni
will be ingraph[j]
.
判斷二分圖。題意是給一個以鄰接表陣列表示的圖,陣列表示的是每個頂點i和他們各自的鄰居節點graph[i]的情況。請你判斷給定的圖是不是二分圖。如果我們能將一個圖的節點集合分割成兩個獨立的子集A和B,並使圖中的每一條邊的兩個節點一個來自A集合,一個來自B集合,我們就將這個圖稱為二分圖。
我這裡提供兩種做法,其實都是塗色法,只是塗色的方式不同。首先是BFS。可以參考這個油管視訊,深刻理解塗色法。大致的思路是,當你遍歷graph裡面的節點的時候,當遇到某一個節點,如果他沒有被染色,你就試圖給他染成某一種顏色,但是對於這個點的所有鄰居節點,需要給他們染成一個別的顏色以區分開。照著這個思路,你需要確保鄰居節點被染成不同的顏色。如果遍歷結束,所有節點都被染色成功,則說明是一個二分圖;如果在染色過程中發現有節點已經被染色但是染色錯誤,則這個圖不是二分圖。既然是BFS,就會需要一個queue來遍歷圖的每一個節點。其他部分請參見程式碼,都非常直觀。
時間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 if (graph[i].length != 0 && visited[i] == 0) { 6 visited[i] = 1; 7 Queue<Integer> queue = new LinkedList<>(); 8 queue.offer(i); 9 while (!queue.isEmpty()) { 10 int cur = queue.poll(); 11 for (int next : graph[cur]) { 12 if (visited[next] == 0) { 13 visited[next] = visited[cur] == 1 ? 2 : 1; 14 queue.offer(next); 15 } else { 16 if (visited[next] == visited[cur]) { 17 return false; 18 } 19 } 20 } 21 } 22 } 23 } 24 return true; 25 } 26 }
DFS。思路跟BFS幾乎沒什麼兩樣,無非是DFS往下層尋找的時候,塗色是按一正一負這樣塗的,而BFS是塗成1或2。
時間O(V + E)
空間O(n)
Java實現
1 class Solution { 2 public boolean isBipartite(int[][] graph) { 3 int[] colors = new int[graph.length]; 4 for (int i = 0; i < graph.length; i++) { 5 if (colors[i] == 0 && !dfs(graph, colors, 1, i)) { 6 return false; 7 } 8 } 9 return true; 10 } 11 12 private boolean dfs(int[][] graph, int[] colors, int color, int node) { 13 if (colors[node] != 0) { 14 return colors[node] == color; 15 } else { 16 colors[node] = color; 17 for (int neigh : graph[node]) { 18 if (!dfs(graph, colors, -color, neigh)) { 19 return false; 20 } 21 } 22 } 23 return true; 24 } 25 }