1. 程式人生 > 實用技巧 >[LeetCode] 785. Is Graph Bipartite?

[LeetCode] 785. Is Graph Bipartite?

Given an undirectedgraph, returntrueif 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

for which the edge between nodesiandjexists. Each node is an integer between0andgraph.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:

  • graphwill have length in range[1, 100].
  • graph[i]will contain integers in range[0, graph.length - 1]
    .
  • graph[i]will not containior duplicate values.
  • The graph is undirected: if any elementjis ingraph[i], theniwill 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 }

LeetCode 題目總結