LeetCode 130题详解:深度优先搜索与广度优先搜索解决被围绕的区域

发布于:2024-05-23 ⋅ 阅读:(150) ⋅ 点赞:(0)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣!

期待与您一起探索技术、持续学习、一步步打怪升级 欢迎订阅本专栏❤️❤️

解读力扣第 130 题:被围绕的区域

在本篇文章中,我们将详细解读力扣第 130 题“被围绕的区域”。通过学习本篇文章,读者将掌握如何使用深度优先搜索(DFS)或广度优先搜索(BFS)来解决二维网格问题的技巧。

问题描述

力扣第 130 题“被围绕的区域”描述如下:

给你一个 m x n 的二维矩阵 board,由 'X''O' 组成。找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O''X' 填充。

示例 1:

输入: board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出: [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]

示例 2:

输入: board = [["X"]]
输出: [["X"]]

解题思路

  1. 初步分析

    • 我们需要找到所有被 'X' 围绕的 'O' 区域,并将这些 'O' 替换为 'X'
    • 如果一个 'O' 位于边界上或连接到边界上的 'O',则不能被替换。
  2. DFS/BFS方法

    • 我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来标记从边界上开始的 'O',这些 'O' 不能被替换。
    • 然后遍历整个网格,将未标记的 'O' 替换为 'X',标记的 'O' 恢复原状。

代码实现

解法一:深度优先搜索(DFS)方法
  1. 步骤

    • 从网格的四个边界开始,进行DFS,将连接到边界的 'O' 标记为临时字符 'T'
    • 遍历整个网格,将未被标记的 'O' 替换为 'X',将标记的 'T' 恢复为 'O'
  2. 伪代码

    def dfs(board, i, j):
        if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != 'O':
            return
        board[i][j] = 'T'
        dfs(board, i + 1, j)
        dfs(board, i - 1, j)
        dfs(board, i, j + 1)
        dfs(board, i, j - 1)
    
代码实现
def solve(board):
    if not board or not board[0]:
        return

    m, n = len(board), len(board[0])

    def dfs(i, j):
        if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != 'O':
            return
        board[i][j] = 'T'
        dfs(i + 1, j)
        dfs(i - 1, j)
        dfs(i, j + 1)
        dfs(i, j - 1)

    # 从边界开始DFS,将所有连接的'O'标记为'T'
    for i in range(m):
        dfs(i, 0)
        dfs(i, n - 1)
    for j in range(n):
        dfs(0, j)
        dfs(m - 1, j)

    # 遍历整个网格,将未被标记的'O'替换为'X',将标记的'T'恢复为'O'
    for i in range(m):
        for j in range(n):
            if board[i][j] == 'O':
                board[i][j] = 'X'
            elif board[i][j] == 'T':
                board[i][j] = 'O'

# 测试案例
board1 = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
solve(board1)
print(board1)  # [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]

board2 = [["X"]]
solve(board2)
print(board2)  # [["X"]]

复杂度分析

  • 时间复杂度:O(m * n),其中 m 是网格的行数,n 是网格的列数。每个点最多被访问两次。
  • 空间复杂度:O(m * n),递归调用栈的最大深度。

代码优化

解法二:广度优先搜索(BFS)方法
  1. 步骤

    • 使用队列从边界开始进行广度优先搜索(BFS),将连接到边界的 'O' 标记为临时字符 'T'
    • 遍历整个网格,将未被标记的 'O' 替换为 'X',将标记的 'T' 恢复为 'O'
  2. 伪代码

    def bfs(board, i, j):
        queue.append((i, j))
        while queue:
            x, y = queue.pop(0)
            if x < 0 or x >= m or y < 0 or y >= n or board[x][y] != 'O':
                continue
            board[x][y] = 'T'
            queue.append((x + 1, y))
            queue.append((x - 1, y))
            queue.append((x, y + 1))
            queue.append((x, y - 1))
    
代码实现
from collections import deque

def solve(board):
    if not board or not board[0]:
        return

    m, n = len(board), len(board[0])

    def bfs(i, j):
        queue = deque([(i, j)])
        while queue:
            x, y = queue.popleft()
            if x < 0 or x >= m or y < 0 or y >= n or board[x][y] != 'O':
                continue
            board[x][y] = 'T'
            queue.append((x + 1, y))
            queue.append((x - 1, y))
            queue.append((x, y + 1))
            queue.append((x, y - 1))

    # 从边界开始BFS,将所有连接的'O'标记为'T'
    for i in range(m):
        bfs(i, 0)
        bfs(i, n - 1)
    for j in range(n):
        bfs(0, j)
        bfs(m - 1, j)

    # 遍历整个网格,将未被标记的'O'替换为'X',将标记的'T'恢复为'O'
    for i in range(m):
        for j in range(n):
            if board[i][j] == 'O':
                board[i][j] = 'X'
            elif board[i][j] == 'T':
                board[i][j] = 'O'

# 测试案例
board1 = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
solve(board1)
print(board1)  # [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]

board2 = [["X"]]
solve(board2)
print(board2)  # [["X"]]

复杂度分析

  • 时间复杂度:O(m * n),其中 m 是网格的行数,n 是网格的列数。每个点最多被访问两次。
  • 空间复杂度:O(min(m, n)),用于队列存储的空间。

总结

本文详细解读了力扣第 130 题“被围绕的区域”,通过深度优先搜索(DFS)和广度优先搜索(BFS)两种不同的解法,帮助读者深入理解二维网格问题的解决思路。希望读者通过本文的学习,能够在力扣刷题的过程中更加得心应手。

参考资料

  • 《算法导论》—— Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein
  • 力扣官方题解

🌹🌹如果觉得这篇文对你有帮助的话,记得一键三连关注、赞👍🏻、收藏是对作者最大的鼓励,非常感谢 ❥(^_-)

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到