LeetCode 岛屿数量学习笔记
2023-12-27 19:29:00
大家好,今天给大家分享下一道 LeetCode 中等难度 的题目200. 岛屿数量。这道题考察的是 Graph 的应用,如何使用 DFS 来 BFS 遍历节点。
题目分析
给定一个由 0 和 1 组成的二维网格,其中 0 表示水,1 表示陆地。一个岛屿是由相邻的 1 (水平或垂直) 组成的区域。请计算网格中岛屿的数量。
例如,给定如下网格:
11110
11010
11000
00000
岛屿的数量为 1 。
解法一:DFS
深度优先搜索(DFS)是一种遍历 Graph 的算法。它从一个节点开始,并沿着一条边走到另一个节点,然后继续遍历该节点的邻接节点,直到没有更多节点可供遍历。DFS 的实现可以使用栈数据结构。
对于这道题,我们可以使用 DFS 来遍历网格中的节点。当我们遇到一个 1 时,我们就从这个节点开始 DFS,并把这个节点的所有相邻节点加入栈中。然后,我们继续遍历栈中的节点,直到栈为空。
def num_islands_dfs(grid):
"""
计算网格中岛屿的数量。
参数:
grid: 一个由 0 和 1 组成的二维网格。
返回:
岛屿的数量。
"""
if not grid:
return 0
# 初始化岛屿数量为 0。
num_islands = 0
# 遍历网格中的每个节点。
for i in range(len(grid)):
for j in range(len(grid[0])):
# 如果当前节点是 1,则表明它是陆地。
if grid[i][j] == 1:
# 从当前节点开始 DFS。
dfs(grid, i, j)
# 岛屿数量加 1。
num_islands += 1
return num_islands
def dfs(grid, i, j):
"""
从 (i, j) 节点开始 DFS。
参数:
grid: 一个由 0 和 1 组成的二维网格。
i: 当前节点的行索引。
j: 当前节点的列索引。
"""
# 如果当前节点越界,或者不是陆地,则返回。
if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == 0:
return
# 将当前节点标记为已访问。
grid[i][j] = 0
# 遍历当前节点的相邻节点。
dfs(grid, i - 1, j) # 上
dfs(grid, i + 1, j) # 下
dfs(grid, i, j - 1) # 左
dfs(grid, i, j + 1) # 右
解法二:BFS
广度优先搜索(BFS)也是一种遍历 Graph 的算法。它从一个节点开始,并把这个节点的所有相邻节点加入队列中。然后,我们从队列中取出一个节点,并把这个节点的所有相邻节点加入队列中。我们继续重复这个过程,直到队列为空。
对于这道题,我们可以使用 BFS 来遍历网格中的节点。当我们遇到一个 1 时,我们就从这个节点开始 BFS,并把这个节点的所有相邻节点加入队列中。然后,我们继续从队列中取出节点,并把这个节点的所有相邻节点加入队列中。直到队列为空,我们就可以得到网格中岛屿的数量。
def num_islands_bfs(grid):
"""
计算网格中岛屿的数量。
参数:
grid: 一个由 0 和 1 组成的二维网格。
返回:
岛屿的数量。
"""
if not grid:
return 0
# 初始化岛屿数量为 0。
num_islands = 0
# 遍历网格中的每个节点。
for i in range(len(grid)):
for j in range(len(grid[0])):
# 如果当前节点是 1,则表明它是陆地。
if grid[i][j] == 1:
# 从当前节点开始 BFS。
bfs(grid, i, j)
# 岛屿数量加 1。
num_islands += 1
return num_islands
def bfs(grid, i, j):
"""
从 (i, j) 节点开始 BFS。
参数:
grid: 一个由 0 和 1 组成的二维网格。
i: 当前节点的行索引。
j: 当前节点的列索引。
"""
# 创建一个队列。
queue = [(i, j)]
# 遍历队列中的每个节点。
while queue:
# 从队列中取出一个节点。
i, j = queue.pop(0)
# 如果当前节点越界,或者不是陆地,则跳过。
if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == 0:
continue
# 将当前节点标记为已访问。
grid[i][j] = 0
# 把当前节点的所有相邻节点加入队列中。
queue.append((i - 1, j)) # 上
queue.append((i + 1, j)) # 下
queue.append((i, j - 1)) # 左
queue.append((i, j + 1)) # 右
总结
这道题考察的是 Graph 的应用,如何使用 DFS 来 BFS 遍历节点。DFS 和 BFS 都是遍历 Graph 的两种常见算法,它们各有优缺点。DFS 的优点是空间复杂度低,但缺点是可能会陷入死循环。BFS 的优点是空间复杂度高,但缺点是不会陷入死循环。对于这道题,我们可以使用 DFS 和 BFS 来解决,但使用 BFS 的解法更简单一些。