力扣130. 被围绕的区域(深度、广度遍历、递归、C++)

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域

  • 连接:一个单元格与水平或垂直方向上相邻的单元格连接。
  • 区域:连接所有 'O' 的单元格来形成一个区域。
  • 围绕:如果您可以用 'X' 单元格 连接这个区域,并且区域中没有任何单元格位于 board 边缘,则该区域被 'X' 单元格围绕。

通过将输入矩阵 board 中的所有 '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"]]

解释:

在上图中,底部的区域没有被捕获,因为它在 board 的边缘并且不能被围绕。

示例 2:

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

输出:[["X"]]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 200
  • board[i][j] 为 'X' 或 'O'

解法一:深度优先遍历 

class Solution {
public:
    int n, m;

    void dfs(vector<vector<char>>& board, int x, int y) {
        if (x < 0 || x >= n || y < 0 || y >= m || board[x][y] != 'O') {
            return;
        }

        board[x][y] = 'A'; // 标记为 'A'
        // 递归调用四个方向
        dfs(board, x + 1, y);
        dfs(board, x - 1, y);
        dfs(board, x, y + 1);
        dfs(board, x, y - 1);
    }

    void solve(vector<vector<char>>& board) {
        n = board.size();
        if (n == 0)
            return;
        m = board[0].size();

        // 从第一列和最后一列进行 DFS
        for (int i = 0; i < n; i++) {
            dfs(board, i, 0);     // 左边界
            dfs(board, i, m - 1); // 右边界
        }
        // 从第一行和最后一行进行 DFS
        for (int i = 1; i < m - 1; i++) {
            dfs(board, 0, i);     // 上边界
            dfs(board, n - 1, i); // 下边界
        }

        // 更新 board,将 'A' 还原为 'O',将 'O' 变为 'X'
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (board[i][j] == 'A')
                    board[i][j] = 'O';
                else if (board[i][j] == 'O')
                    board[i][j] = 'X';
            }
        }
    }
};

解决思路如下:

  1. 首先定义了变量n和m,分别存储矩阵的行数和列数。
  2. 定义了dfs函数,用于进行深度优先搜索。dfs函数的输入参数有目标矩阵board,当前搜索位置的坐标x和y。
  3. 在dfs函数中,首先进行边界条件判断。如果当前坐标超出了矩阵的范围,或者当前位置上的字符不是'O',则直接返回。
  4. 如果当前位置上的字符是'O',则将其改为字符'A',表示已经访问过。
  5. 递归调用dfs函数,分别搜索四个方向上的相邻位置:右、左、下、上。
  6. 在solve函数中,首先获取矩阵的行数和列数,并进行边界判断,如果行数为0,则直接返回。
  7. 接着从第一列和最后一列开始进行dfs搜索,对于每一行,分别调用dfs函数,传入矩阵坐标i和列坐标0以及列坐标m-1。
  8. 再从第一行和最后一行开始进行dfs搜索,对于每一列,分别调用dfs函数,传入矩阵坐标0和行坐标i以及行坐标n-1。
  9. 最后,遍历整个矩阵,将字符'A'改为'O',将字符'O'改为'X'。

整体思路是从矩阵的边界开始进行DFS搜索,将所有与边界相连的字符'O'标记为字符'A',表示不会被改变的区域。然后再遍历整个矩阵,将字符'O'改为字符'X',将字符'A'改回字符'O',即实现了将被围绕的区域替换为'X'的要求。


解法二:广度优先遍历 

class Solution {
public:
    const int dx[4] = {1, -1, 0, 0};
    const int dy[4] = {0, 0, 1, -1};
    void solve(vector<vector<char>>& board) {
        int n=board.size();
        if(n==0)
        return ;
        int m=board[0].size();

        queue<pair<int ,int>> que;

        for(int i=0;i<n;i++){
            if(board[i][0]=='O'){
                que.emplace(i,0);
                board[i][0]='A';
            }
            if(board[i][m-1]=='O'){
                que.emplace(i,m-1);
                board[i][m-1]='A';
            }
        }

        for(int i=1;i<m-1;i++){
            if(board[0][i]=='O'){
                que.emplace(0,i);
                board[0][i]='A';
            }
            if(board[n-1][i]=='O'){
                que.emplace(n-1,i);
                board[n-1][i]='A';
            }
        }

        while(!que.empty()){
            int x=que.front().first,y=que.front().second;
            que.pop();

            for(int i=0;i<4;i++){
                int mx=x+dx[i],my=y+dy[i];
                if(mx<0||my<0||mx>=n||my>=m||board[mx][my]!='O')
                continue;
                que.emplace(mx,my);
                board[mx][my]='A';
            }
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]=='A')
                board[i][j]='O';
                else if(board[i][j]=='O')
                board[i][j]='X';
            }
        }
    }
};

解决思路如下:

  1. 首先定义了常量数组dx和dy,表示四个方向的x和y的增量。
  2. 定义了solve函数,用于解决问题。solve函数的输入参数是二维字符矩阵board。
  3. 首先获取矩阵的行数n和列数m,并进行边界判断,如果行数为0,则直接返回。
  4. 定义一个队列que,用于存储待访问的坐标。
  5. 遍历矩阵的边界,如果当前位置上的字符是'O',则将其坐标加入队列que,并将其标记为字符'A'。
  6. 使用队列进行广度优先搜索。当队列不为空时,取出队首元素,获取其坐标x和y。
  7. 遍历四个方向,计算出相邻位置的坐标mx和my。
  8. 如果相邻位置超出了矩阵的范围,或者相邻位置上的字符不是'O',则跳过当前方向。
  9. 如果相邻位置上的字符是'O',则将其坐标加入队列que,并将其标记为字符'A'。
  10. 当队列为空时,表示所有与边界相连的字符'O'都已经标记为字符'A'。
  11. 遍历整个矩阵,将字符'A'改为字符'O',将字符'O'改为'X'。

整体思路是从矩阵的边界开始进行广度优先搜索,将所有与边界相连的字符'O'标记为字符'A',表示不会被改变的区域。然后再遍历整个矩阵,将字符'O'改为字符'X',将字符'A'改回字符'O',即实现了将被围绕的区域替换为'X'的要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值