返回

图解LeetCode——200. 岛屿数量

后端

如何征服 LeetCode 第 200 题:“岛屿数量”

准备好潜入算法问题的海洋了吗?让我们共同征服 LeetCode 第 200 题:“岛屿数量”。在这篇文章中,我们将探索三种解决此问题的强大算法:深度优先搜索、广度优先搜索和并查集算法。

1. 深度优先搜索:深入探险

想象一下自己像一位探险家,深入探索一个迷宫。深度优先搜索(DFS)就是这样的算法,它沿着一条路径一直探索下去,直到遇到死路,然后再回溯寻找其他路径。在我们的“岛屿数量”问题中,DFS 会从网格的一角开始,标记陆地并继续搜索相邻的陆地。当它完成探索后,就会返回岛屿数量。

优点:

  • 易于理解和实现
  • 内存消耗较小

缺点:

  • 可能出现栈溢出问题

2. 广度优先搜索:逐层拓展

广度优先搜索(BFS)就像一个拓荒者,它一层一层地探索网格,从未被访问过的陆地开始。BFS 会将陆地添加到一个队列中,并一层一层地探索它们。通过这种方法,它可以避免栈溢出问题。

优点:

  • 避免栈溢出问题
  • 适用于大网格

缺点:

  • 可能会探索一些不必要的区域

3. 并查集算法:高效管理

并查集算法是一个强大的数据结构,它可以管理元素集合。在我们的问题中,我们将每个陆地视为一个集合。并查集算法会将相邻的陆地合并到同一个集合中,最后返回集合数量,即岛屿数量。

优点:

  • 高效处理大量数据
  • 无需遍历整个网格

缺点:

  • 实现复杂度高

代码示例:

Python (DFS):

def num_islands(grid):
    def dfs(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(i + 1, j)
        dfs(i - 1, j)
        dfs(i, j + 1)
        dfs(i, j - 1)

    count = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1':
                count += 1
                dfs(i, j)

    return count

Python (BFS):

from collections import deque

def num_islands(grid):
    def bfs(i, j):
        queue = deque([(i, j)])
        while queue:
            x, y = queue.popleft()
            if x < 0 or x >= len(grid) or y < 0 or y >= len(grid[0]) or grid[x][y] == '0':
                continue

            grid[x][y] = '0'  # 标记已访问
            queue.append((x + 1, y))
            queue.append((x - 1, y))
            queue.append((x, y + 1))
            queue.append((x, y - 1))

    count = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1':
                count += 1
                bfs(i, j)

    return count

Python (并查集):

class UnionFind:
    def __init__(self):
        self.parent = {}

    def find(self, x):
        if x not in self.parent:
            self.parent[x] = x
        elif self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x != root_y:
            self.parent[root_x] = root_y

def num_islands(grid):
    uf = UnionFind()
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1':
                if i > 0 and grid[i - 1][j] == '1':
                    uf.union((i, j), (i - 1, j))
                if j > 0 and grid[i][j - 1] == '1':
                    uf.union((i, j), (i, j - 1))

    count = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1' and uf.find((i, j)) == (i, j):
                count += 1

    return count

常见问题解答

1. 哪种算法最适合解决“岛屿数量”问题?

这取决于网格的大小和特定情况。对于小网格,DFS 和 BFS 都可以很好地工作。对于大网格,并查集算法更有效。

2. DFS 和 BFS 有什么区别?

DFS 深入探索一条路径,而 BFS 逐层拓展。DFS 可能遇到栈溢出问题,而 BFS 可以避免这个问题。

3. 并查集算法如何工作?

并查集算法使用两个操作:合并和查找。合并将集合合并在一起,查找返回一个元素所属的集合。

4. 为什么并查集算法比 DFS 和 BFS 更高效?

并查集算法无需遍历整个网格,因为它使用并查集数据结构高效地管理集合。

5. “岛屿数量”问题还有其他解决方法吗?

是的,还有其他解决方法,如循环检测或图像处理技术。