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

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

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

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

解读力扣第 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',则不能被替换。
  1. DFS/BFS方法
  • 我们可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来标记从边界上开始的 'O',这些 'O' 不能被替换。
  • 然后遍历整个网格,将未标记的 'O' 替换为 'X',标记的 'O' 恢复原状。

代码实现

解法一:深度优先搜索(DFS)方法
  1. 步骤
  • 从网格的四个边界开始,进行DFS,将连接到边界的 'O' 标记为临时字符 'T'
  • 遍历整个网格,将未被标记的 'O' 替换为 'X',将标记的 'T' 恢复为 'O'
  1. 伪代码
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'
  1. 伪代码
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
  • 力扣官方题解

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

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)

欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
6月前
|
算法 测试技术
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
|
6月前
|
算法 测试技术 C++
【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数
【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数
|
5月前
|
存储 算法 数据可视化
LeetCode 133题详解:广度优先搜索和深度优先搜索实现克隆图
LeetCode 133题详解:广度优先搜索和深度优先搜索实现克隆图
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏
【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏
|
5月前
|
存储 算法 数据可视化
广度优先搜索(BFS)+回溯解决LeetCode 126题:单词接龙 II
广度优先搜索(BFS)+回溯解决LeetCode 126题:单词接龙 II
|
5月前
|
存储 算法 数据可视化
LeetCode 题目 97:动态规划、递归到广度优先搜索BFS 实现交错字符串
LeetCode 题目 97:动态规划、递归到广度优先搜索BFS 实现交错字符串
|
6月前
|
算法 测试技术 C#
【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数
【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数
|
算法
从三道leetcode掌握深度优先搜索(DFS)
前言 无论在算法面试还是刷题中,深度优先搜索(DFS)和广度优先搜索(BFS)都是一个绕不过去的坎。不同于数组的从左至右遍历,循环常用于一维数据结构的遍历。而DFS和BFS则常用于多维数据结构的遍历,最常见的莫过于嵌套结构的多叉树了。
从三道leetcode掌握广度优先搜索(BFS)
前言 BFS和DFS是如影随形的两种搜索方式,我们在上篇文章从三道leetcode掌握深度优先搜索(DFS)学习了递归的概念及DFS。不熟悉递归及DFS的同学可以先看看上篇文章,再阅读本篇比较好。
leetcode 130 被围绕的区域
leetcode 130 被围绕的区域
68 0
leetcode 130 被围绕的区域