返回

探索LeetCode 429:以惊艳的技巧发现隐藏的岛屿!

闲谈

在数字之海中,探寻岛屿的踪迹

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的关键,它们各有优劣,在不同的情况下可以发挥不同的作用。
  • 代码是算法的载体: 代码是算法的具体实现,它将算法的逻辑转化为计算机可以执行的指令。
  • 实践是检验真理的唯一标准: 算法和编程的学习离不开实践,只有通过不断地练习,才能真正掌握算法和编程的精髓。