返回
探索LeetCode 429:以惊艳的技巧发现隐藏的岛屿!
闲谈
2023-11-25 16:48:34
在数字之海中,探寻岛屿的踪迹
LeetCode 429,犹如一面镜子,映照出我们对于算法和编程的理解。在数字化的海洋中,我们化身探险家,在网格的世界里寻找隐藏的岛屿。每一格方块,都可能成为岛屿的一部分。有的岛屿相互连接,形成一片陆地;有的岛屿却孑然独立,诉说着孤寂的故事。而我们的任务,就是揭开这数字之海的神秘面纱,找到所有隐藏的岛屿,计算它们的个数,绘出它们的版图。
两大算法,奏响解决问题的交响曲
在解决LeetCode 429的征程中,我们有两个强有力的武器:深度优先搜索和广度优先搜索。
- 深度优先搜索(DFS): 它是算法界的探险家,沿着一条道路走到底,再回过头来探索其他可能。DFS以递归的方式运作,在网格中不断深入,直到遇到水域或已经探索过的陆地。每当遇到一个新的岛屿,它便标记下这个岛屿的边界,继续探索下一个岛屿。
- 广度优先搜索(BFS): 它是算法界的拓荒者,先探索网格中的所有相邻方块,然后再继续深入。BFS使用队列来管理要探索的方块,依次将它们加入队列中,然后从队列中取出方块进行探索。每当遇到一个新的岛屿,它便标记下这个岛屿的边界,并将这个岛屿的所有相邻方块加入队列,继续探索。
代码实现,展现算法的魅力
理论知识固然重要,但实践才是检验真理的唯一标准。以下是用Python语言实现的LeetCode 429的代码:
def num_islands(grid):
"""
计算网格中岛屿的数量。
Args:
grid: 一个由 '1'(陆地)和 '0'(水)组成的二维网格。
Returns:
岛屿的数量。
"""
# 检查网格是否为空或空字符串
if not grid or not grid[0]:
return 0
# 初始化一个二维数组来标记已经访问过的方块
visited = [[False for _ in row] for row in grid]
# 初始化岛屿数量
island_count = 0
# 遍历网格
for i in range(len(grid)):
for j in range(len(grid[0])):
# 如果当前方块是陆地并且还没有被访问过
if grid[i][j] == '1' and not visited[i][j]:
# 这是一个新的岛屿,增加岛屿数量
island_count += 1
# 用深度优先搜索或广度优先搜索探索这个岛屿
# 标记所有属于这个岛屿的方块为已访问
dfs(grid, visited, i, j)
return island_count
def dfs(grid, visited, i, j):
"""
使用深度优先搜索探索岛屿。
Args:
grid: 一个由 '1'(陆地)和 '0'(水)组成的二维网格。
visited: 一个二维数组,标记已经访问过的方块。
i: 当前方块的行索引。
j: 当前方块的列索引。
"""
# 检查当前方块是否有效
if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]):
return
# 检查当前方块是否是陆地并且还没有被访问过
if grid[i][j] == '0' or visited[i][j]:
return
# 标记当前方块为已访问
visited[i][j] = True
# 探索当前方块的四个相邻方块
dfs(grid, visited, i - 1, j) # 上方
dfs(grid, visited, i + 1, j) # 下方
dfs(grid, visited, i, j - 1) # 左方
dfs(grid, visited, i, j + 1) # 右方
def bfs(grid, visited, i, j):
"""
使用广度优先搜索探索岛屿。
Args:
grid: 一个由 '1'(陆地)和 '0'(水)组成的二维网格。
visited: 一个二维数组,标记已经访问过的方块。
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]):
continue
# 检查当前方块是否是陆地并且还没有被访问过
if grid[i][j] == '0' or visited[i][j]:
continue
# 标记当前方块为已访问
visited[i][j] = True
# 将当前方块的四个相邻方块加入队列
queue.append((i - 1, j)) # 上方
queue.append((i + 1, j)) # 下方
queue.append((i, j - 1)) # 左方
queue.append((i, j + 1)) # 右方
总结:在算法的世界中乘风破浪
LeetCode 429教会了我们许多宝贵的经验:
- 算法是解决问题的利器: 算法是计算机科学的核心,它帮助我们以更有效的方式解决问题。
- 深度优先搜索和广度优先搜索是两大重要的算法: 这两种算法是解决LeetCode 429的关键,它们各有优劣,在不同的情况下可以发挥不同的作用。
- 代码是算法的载体: 代码是算法的具体实现,它将算法的逻辑转化为计算机可以执行的指令。
- 实践是检验真理的唯一标准: 算法和编程的学习离不开实践,只有通过不断地练习,才能真正掌握算法和编程的精髓。