@@ -26,8 +26,12 @@ graph = {
2626
2727该无向图的结构如图左所示,图右为宽度优先搜索的遍历路径。
2828
29+ ![ ] ( https://qcdn.itcharge.cn/images/20220105135253.png )
30+
2931其对应的动态演示图如下所示。
3032
33+ ![ ] ( https://qcdn.itcharge.cn/images/20220105135158.gif )
34+
3135## 3. 基于队列实现的广度优先搜索
3236
3337### 3.1 基于队列实现的广度优先搜索实现步骤
@@ -43,27 +47,91 @@ graph = {
4347### 3.2 基于队列实现的广度优先搜索实现代码
4448
4549``` Python
46- from queue import Queue
50+ import collections
4751
4852def bfs (graph , start ):
4953 visited = set (start)
50- q = Queue( )
51- q.put(start)
52- while not q.empty() :
53- node_u = q.get ()
54+ q = collections.deque([start] )
55+
56+ while q :
57+ node_u = q.popleft ()
5458 print (node_u)
5559 for node_v in graph[node_u]:
5660 if node_v not in visited:
5761 visited.add(node_v)
58- q.put (node_v)
62+ q.append (node_v)
5963```
6064
6165## 4. 广度优先搜索应用
6266
63- ### 4.1 岛屿的最大面积
67+ ### 4.1 无向图中连通分量的数目
6468
6569#### 4.1.1 题目链接
6670
71+ - [ 323. 无向图中连通分量的数目 - 力扣(LeetCode)] ( https://leetcode-cn.com/problems/number-of-connected-components-in-an-undirected-graph/ )
72+
73+ #### 4.1.2 题目大意
74+
75+ 给定 ` n ` 个节点(编号从 ` 0 ` 到 ` n - 1 ` )的图的无向边列表 ` edges ` ,其中 ` edges[i] = [u, v] ` 表示节点 ` u ` 和节点 ` v ` 之间有一条无向边。
76+
77+ 要求:计算该无向图中连通分量的数量。
78+
79+ #### 4.1.3 解题思路
80+
81+ 先来看一下图论中相关的名次解释。
82+
83+ - 连通图:在无向图中,如果可以从顶点 $v_i$ 到达 $v_j$,则称 $v_i$ 和 $v_j$ 连通。如果图中任意两个顶点之间都连通,则称该图为连通图。
84+ - 无向图的连通分量:如果该图为连通图,则连通分量为本身;否则将无向图中的极大连通子图称为连通分量,每个连通分量都是一个连通图。
85+ - 无向图的连通分量个数:无向图的极大连通子图的个数。
86+
87+ 接下来我们来解决这道题。
88+
89+ 由于题目给定的是无向边列表。我们先将其转变为邻接表的形式。然后使用广度优先搜索计算联通分量的个数。具体做法如下:
90+
91+ - 使用变量 ` count ` 记录连通分量个数。使用集合变量 ` visited ` 记录访问过的节点,使用邻接表 ` graph ` 记录图结构。
92+ - 从 ` 0 ` 开始,依次遍历 ` n ` 个节点。
93+ - 如果第 ` i ` 个节点未访问过:
94+ - 将其添加到 ` visited ` 中。
95+ - 并且连通分量个数累加,即 ` count += 1 ` 。
96+ - 定义一个队列 ` q ` ,将第 ` i ` 个节点加入到队列中。
97+ - 从队列中取出第一个节点,遍历与其链接的节点,并将未遍历过的节点加入到队列 ` q ` 和 ` visited ` 中。
98+ - 直到队列为空,则继续向后遍历。
99+
100+ - 最后输出连通分量数目 ` count ` 。
101+
102+ #### 4.1.4 代码
103+
104+ ``` Python
105+ import collections
106+
107+ class Solution :
108+ def countComponents (self , n : int , edges : List[List[int ]]) -> int :
109+ count = 0
110+ visited = set ()
111+ graph = [[] for _ in range (n)]
112+
113+ for x, y in edges:
114+ graph[x].append(y)
115+ graph[y].append(x)
116+
117+ for i in range (n):
118+ if i not in visited:
119+ visited.add(i)
120+ count += 1
121+ q = collections.deque([i])
122+ while q:
123+ node_u = q.popleft()
124+ for node_v in graph[node_u]:
125+ if node_v not in visited:
126+ visited.add(node_v)
127+ q.append(node_v)
128+ return count
129+ ```
130+
131+ ### 4.2 岛屿的最大面积
132+
133+ #### 4.2.1 题目链接
134+
67135- [ 695. 岛屿的最大面积 - 力扣(LeetCode)] ( https://leetcode-cn.com/problems/max-area-of-island/ )
68136
69137#### 4.2.2 题目大意
@@ -72,12 +140,52 @@ def bfs(graph, start):
72140
73141要求:计算出最大的岛屿面积。
74142
143+ 示例 :
144+
145+ ![ img] ( https://assets.leetcode.com/uploads/2021/05/01/maxarea1-grid.jpg )
146+
147+ 图中最大的岛屿面积为 6。
148+
75149#### 4.2.3 解题思路
76150
151+ 使用广度优先搜索方法。具体做法如下:
152+
153+ 1 . 使用 ` ans ` 记录最大岛屿面积。
154+ 2 . 遍历二维数组的每一个元素,对于每个值为 ` 1 ` 的元素:
155+ 1 . 将该元素置为 ` 0 ` 。并使用队列 ` q ` 存储该节点位置。使用 ` temp_ans ` 记录当前岛屿面积。
156+ 2 . 然后从队列 ` q ` 中取出第一个节点位置 ` (i, j) ` 。遍历该节点位置上、下、左、右四个方向上的相邻节点。并将其置为 ` 0 ` (避免重复搜索)。并将其加入到队列中。并累加当前岛屿面积,即 ` temp_ans += 1 ` 。
157+ 3 . 不断重复上一步骤,直到队列 ` q ` 为空。
158+ 4 . 更新当前最大岛屿面积,即 ` ans = max(ans, temp_ans) ` 。
159+
77160#### 4.2.4 代码
78161
79162``` Python
80-
163+ import collections
164+
165+ class Solution :
166+ def maxAreaOfIsland (self , grid : List[List[int ]]) -> int :
167+ directs = [(0 , 1 ), (0 , - 1 ), (1 , 0 ), (- 1 , 0 )]
168+ rows, cols = len (grid), len (grid[0 ])
169+ ans = 0
170+ for i in range (rows):
171+ for j in range (cols):
172+ if grid[i][j] == 1 :
173+ grid[i][j] = 0
174+ temp_ans = 1
175+ q = collections.deque([(i, j)])
176+ while q:
177+ i, j = q.popleft()
178+ for direct in directs:
179+ new_i = i + direct[0 ]
180+ new_j = j + direct[1 ]
181+ if new_i < 0 or new_i >= rows or new_j < 0 or new_j >= cols or grid[new_i][new_j] == 0 :
182+ continue
183+ grid[new_i][new_j] = 0
184+ q.append((new_i, new_j))
185+ temp_ans += 1
186+
187+ ans = max (ans, temp_ans)
188+ return ans
81189```
82190
83191## 参考资料
0 commit comments