返回

解谜攻略:用 Python 巧妙地解决 leetcode 130「被围绕的区域」

见解分享

问题陈述

给你一个由 'X' 和 'O' 组成的 m x n 矩阵 board,其中 'X' 表示障碍,'O' 表示空地。一群人在玩井字棋,玩家需要用 'X' 标记空地。但由于疏忽,他们还错误地用 'X' 标记了一些障碍。你的任务是把这些错误标记的 'X' 替换为 'O'。

解题思路

要解决这个问题,我们可以使用深度优先搜索 (DFS) 或广度优先搜索 (BFS) 算法。两种算法都可以有效地遍历矩阵,并确定哪些 'O' 被 'X' 包围。

深度优先搜索 (DFS)

DFS 算法从给定位置出发,沿着一条路径探索,直到到达末端。对于本题,我们可以从每个 'O' 出发,向四个方向 (上、下、左、右) 探索。如果我们遇到一个 'X',则表明当前路径无效,我们停止探索。否则,我们继续沿着该路径探索,直到达到矩阵边界或遇到另一个 'X'。如果我们成功地遍历了整条路径,则表明该 'O' 没有被 'X' 包围,我们将其标记为安全。

广度优先搜索 (BFS)

BFS 算法从给定位置出发,按照层次遍历整个矩阵。对于本题,我们可以从每个 'O' 出发,将其加入队列。然后,我们从队列中取出一个 'O',并向四个方向探索。如果我们遇到一个 'X',则停止探索。否则,我们将遇到的 'O' 加入队列。我们继续这个过程,直到队列为空或矩阵中所有 'O' 都被探索。如果一个 'O' 没有被 'X' 包围,则将其标记为安全。

Python 实现

下面是用 Python 实现的 DFS 算法:

def solve(board):
    m, n = len(board), len(board[0])

    # 定义四个探索方向
    directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]

    # 遍历矩阵,标记安全区域
    for i in range(m):
        for j in range(n):
            if board[i][j] == 'O':
                if i == 0 or j == 0 or i == m - 1 or j == n - 1:
                    # 位于边界上的 'O' 肯定安全
                    dfs(board, i, j)

    # 将错误标记的 'X' 替换为 'O'
    for i in range(m):
        for j in range(n):
            if board[i][j] == 'M':
                board[i][j] = 'O'
            else:
                board[i][j] = 'X'

# 深度优先搜索函数
def dfs(board, i, j):
    if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != 'O':
        return

    # 将当前 'O' 标记为安全
    board[i][j] = 'M'

    # 探索四个方向
    for dx, dy in directions:
        dfs(board, i + dx, j + dy)

时间复杂度

DFS 和 BFS 的时间复杂度均为 O(mn),其中 m 和 n 分别为矩阵的行数和列数。

空间复杂度

DFS 和 BFS 的空间复杂度均为 O(mn),因为我们需要使用额外的空间来存储访问过的元素。

总结

在本文中,我们介绍了解决 leetcode 130「被围绕的区域」问题的两种方法:深度优先搜索 (DFS) 和广度优先搜索 (BFS)。我们还提供了用 Python 实现的 DFS 算法。通过理解这些算法的基本原理并运用 Python 的强大功能,我们可以高效地解决这道有趣而具有挑战性的问题。