leetcode130被围绕的区域

步骤1:问题性质定义

给定一个 m x n 的矩阵 board,矩阵由字符 'X''O' 组成。我们需要捕获所有被 'X' 围绕的 'O' 区域,即将这些 'O' 替换为 'X'。被围绕的 'O' 区域是指这些 'O' 区域完全被 'X' 单元格包围,且该区域不与边缘相连。

输入条件:
  • board 为一个二维矩阵,包含字符 'X''O'
  • mn 为矩阵的行和列,满足 1 <= m, n <= 200
  • board[i][j] 的值为 'X''O'
输出条件:
  • 返回一个二维矩阵,其中所有被 'X' 围绕的 'O' 被替换为 'X',其余的 'O' 保持不变。
限制:
  • mn 的最大值是 200,因此矩阵的最大大小为 40,000 元素,算法需要在合理的时间复杂度内处理。
边界条件:
  • board 中只有 'X''O'
  • board 的尺寸非常小,例如 1x1
  • 边缘上的 'O' 不会被替换。

步骤2:解题思路与步骤分解

问题分析:

我们需要标识出哪些 'O' 是被围绕的。显然,边缘上的 'O' 不会被围绕。最简单的办法是先从边缘的 'O' 开始,使用深度优先搜索(DFS)或广度优先搜索(BFS)将与边缘相连的 'O' 标记为"安全",剩下的 'O' 就是被围绕的区域,可以被替换为 'X'

解决方案:
  1. 标记安全区域
    • 从四个边缘开始遍历所有 'O',如果发现 'O',就用 DFS 或 BFS 将其与相连的 'O' 都标记为"安全"。
  2. 捕获被围绕的区域
    • 遍历整个矩阵,对于每个没有被标记为"安全"的 'O',将其替换为 'X'
    • 对于标记为"安全"的 'O',保持不变。
算法:
  • DFS/BFS :从四个边缘的 'O' 出发,标记所有连接的 'O'
  • 时间复杂度O(m * n),每个单元格最多访问一次。
  • 空间复杂度O(m * n),用于存储标记和递归栈(DFS)或队列(BFS)。

步骤3:C++代码实现

cpp 复制代码
class Solution {
public:
// DFS实现
void dfs(vector<vector<char>>& board, int i, int j) {
    // 边界条件检查
    if (i < 0 || j < 0 || i >= board. size() || j >= board[0].size() || board[i][j] != 'O') {
        return;
    }
    // 标记当前'O'为安全
    board[i][j] = 'S';  // 'S'表示安全的'O'

    // 向四个方向进行DFS
    dfs(board, i + 1, j);  // 向下
    dfs(board, i - 1, j);  // 向上
    dfs(board, i, j + 1);  // 向右
    dfs(board, i, j - 1);  // 向左
}

void solve(vector<vector<char>>& board) {
    if (board. empty() || board[0].empty()) return;

    int m = board.size();
    int n = board[0].size();

    // 从四个边缘开始DFS
    // 遍历第一行和最后一行
    for (int j = 0; j < n; j++) {
        if (board[0][j] == 'O') dfs(board, 0, j); // 第一行
        if (board[m-1][j] == 'O') dfs(board, m-1, j); // 最后一行
    }

    // 遍历第一列和最后一列
    for (int i = 0; i < m; i++) {
        if (board[i][0] == 'O') dfs(board, i, 0); // 第一列
        if (board[i][n-1] == 'O') dfs(board, i, n-1); // 最后一列
    }

    // 修改被围绕的'O'为'X', 将安全的'O'恢复为'O'
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (board[i][j] == 'O') {
                board[i][j] = 'X'; // 被围绕的'O'替换为'X'
            }
            else if (board[i][j] == 'S') {
                board[i][j] = 'O'; // 安全的'O'恢复为'O'
            }
        }
    }
}


};

代码注释:

  1. DFS函数 :用于深度优先搜索,找到与边缘相连的 'O',并将它们标记为 'S'(安全)。
  2. 捕获函数 capture :首先从矩阵的四个边缘开始,找到所有与边缘相连的 'O',标记为安全。然后遍历整个矩阵,捕获所有被 'X' 围绕的 'O',并替换为 'X'
  3. 主函数 :初始化一个示例 board,调用 capture 函数进行处理,最后输出结果。

步骤4:启发

通过这个问题,我们可以学到以下几个启发:

  • 区域标记技术:通过遍历矩阵边缘,将与边缘相连的区域标记为特殊状态(如'S'),然后对其他区域进行处理。这种方法在处理图形或网格类问题时非常常见。
  • DFS/BFS应用:DFS 和 BFS 是解决图形问题的常见算法,能够有效标记与特定节点相连的区域,避免重复计算。
  • 边界条件处理:在解决矩阵问题时,需要特别注意边界条件,确保不会越界或错漏。

步骤5:实际应用

这个算法在很多实际应用中有用,尤其是在图像处理、区域划分和边界检测等领域。以下是一个实际应用示例:

应用示例:图像边界检测与区域填充

在图像处理中,我们可能需要处理图像中的封闭区域,例如通过填充算法填充一个被边界围住的区域。类似于这个问题,图像中可能存在"被围绕"的像素区域(例如,某些区域需要被颜色填充,而不想影响边缘区域)。此时,可以使用类似的 DFS/BFS 技术从边缘开始扫描,标记不需要填充的区域,最后进行填充。

实现方法

  1. 对于二值图像(0表示背景,1表示前景),从图像的边缘开始,找到所有与背景相连的前景像素。
  2. 将所有与边缘相连的前景像素标记为"安全"。
  3. 将剩余的前景像素填充为背景颜色。

这种方法被广泛应用于图像编辑软件中,用于实现区域填充、图像剪裁等功能。

相关推荐
PAK向日葵30 分钟前
【算法导论】XM 0823 笔试题解
算法·面试
岁月栖迟33 分钟前
leetcode 49. 字母异位词分组
windows·算法·leetcode
Asmalin33 分钟前
【代码随想录day 21】 力扣 77. 组合
算法·leetcode·职场和发展
2501_924878596 小时前
强光干扰下漏检率↓78%!陌讯动态决策算法在智慧交通违停检测的实战优化
大数据·深度学习·算法·目标检测·视觉检测
耳总是一颗苹果6 小时前
排序---插入排序
数据结构·算法·排序算法
YLCHUP7 小时前
【联通分量】题解:P13823 「Diligent-OI R2 C」所谓伊人_连通分量_最短路_01bfs_图论_C++算法竞赛
c语言·数据结构·c++·算法·图论·广度优先·图搜索算法
花火|7 小时前
算法训练营day62 图论⑪ Floyd 算法精讲、A star算法、最短路算法总结篇
算法·图论
GuGu20247 小时前
新手刷题对内存结构与形象理解的冲突困惑
算法
汤永红7 小时前
week4-[二维数组]平面上的点
c++·算法·平面·信睡奥赛
晴空闲雲8 小时前
数据结构与算法-字符串、数组和广义表(String Array List)
数据结构·算法