785. Is Graph Bipartite? 判断二分图
Title
給定一個無向圖graph,當這個圖為二分圖時返回true。
如果我們能將一個圖的節點集合分割成兩個獨立的子集A和B,并使圖中的每一條邊的兩個節點一個來自A集合,一個來自B集合,我們就將這個圖稱為二分圖。
graph將會以鄰接表方式給出,graph[i]表示圖中與節點i相連的所有節點。每個節點都是一個在0到graph.length-1之間的整數。這圖中沒有自環和平行邊: graph[i] 中不存在i,并且graph[i]中沒有重復的值。
示例 1:
輸入: [[1,3], [0,2], [1,3], [0,2]]
輸出: true
解釋:
無向圖如下:
我們可以將節點分成兩組: {0, 2} 和 {1, 3}。
示例 2:
輸入: [[1,2,3], [0,2], [0,1,3], [0,2]]
輸出: false
解釋:
無向圖如下:
我們不能將節點分割成兩個獨立的子集。
注意:
- graph 的長度范圍為 [1, 100]。
- graph[i] 中的元素的范圍為 [0, graph.length - 1]。
- graph[i] 不會包含 i 或者有重復的值。
- 圖是無向的: 如果j 在 graph[i]里邊, 那么 i 也會在 graph[j]里邊。
Solve
對于圖中的任意兩個節點 u 和 v,如果它們之間有一條邊直接相連,那么 u 和 v 必須屬于不同的集合。
如果給定的無向圖連通,那么我們就可以任選一個節點開始,給它染成紅色。隨后我們對整個圖進行遍歷,將該節點直接相連的所有節點染成綠色,表示這些節點不能與起始節點屬于同一個集合。我們再將這些綠色節點直接相連的所有節點染成紅色,以此類推,直到無向圖中的每個節點均被染色。
如果我們能夠成功染色,那么紅色和綠色的節點各屬于一個集合,這個無向圖就是一個二分圖;如果我們未能成功染色,即在染色的過程中,某一時刻訪問到了一個已經染色的節點,并且它的顏色與我們將要給它染上的顏色不相同,也就說明這個無向圖不是一個二分圖。
算法的流程如下:
- 我們任選一個節點開始,將其染成紅色,并從該節點開始對整個無向圖進行遍歷;
- 在遍歷的過程中,如果我們通過節點 u 遍歷到了節點 v(即 u 和 v 在圖中有一條邊直接相連),那么會有兩種情況:
- 如果 v 未被染色,那么我們將其染成與 u 不同的顏色,并對 v 直接相連的節點進行遍歷;
- 如果 v 被染色,并且顏色與 u 相同,那么說明給定的無向圖不是二分圖。我們可以直接退出遍歷并返回 False 作為答案。
- 當遍歷結束時,說明給定的無向圖是二分圖,返回 True 作為答案。
注意:題目中給定的無向圖不一定保證連通,因此我們需要進行多次遍歷,直到每一個節點都被染色,或確定答案為 False 為止。每次遍歷開始時,我們任選一個未被染色的節點,將所有與該節點直接或間接相連的節點進行染色。
深度優先搜索
Code
def isBipartite_DFS(self, graph: List[List[int]]) -> bool:n, unColored, red, green = len(graph), 0, 1, 2color, valid = [unColored] * n, Truedef dfs(node: int, c: int):nonlocal validcolor[node] = cnextC = (green if c == red else red)for neighbor in graph[node]:if color[neighbor] == unColored:dfs(neighbor, nextC)if not valid:returnelif color[neighbor] != nextC:valid = Falsereturnfor i in range(n):if color[i] == unColored:dfs(i, red)if not valid:breakreturn valid復雜度分析
時間復雜度:O(N+M),其中 N 和 M 分別是無向圖中的點數和邊數。
空間復雜度:O(N),存儲節點顏色的數組需要 O(N) 的空間,并且在深度優先搜索的過程中,棧的深度最大為 N,需要 O(N) 的空間。
廣度優先搜索
Code
def isBipartite_BFS(self, graph: List[List[int]]) -> bool:n, unColored, red, green = len(graph), 0, 1, 2color = [unColored] * nfor i in range(n):if color[i] == unColored:q = collections.deque([i])color[i] = redwhile q:node = q.popleft()nextC = (green if color[node] == red else red)for neighbor in graph[node]:if color[neighbor] == unColored:q.append(neighbor)color[neighbor] = nextCelif color[neighbor] != nextC:return Falsereturn True復雜度分析
時間復雜度:O(N+M),其中 N 和 M 分別是無向圖中的點數和邊數。
空間復雜度:O(N),存儲節點顏色的數組需要 O(N) 的空間,并且在廣度優先搜索的過程中,隊列中最多有 N-1 個節點,需要 O(N) 的空間。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的785. Is Graph Bipartite? 判断二分图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5.Vue 计算属性和侦听器
- 下一篇: 编写你的第一个 Django 应用,第