【leetcode解题】130.被环绕的区域

130. 被围绕的区域

给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。

示例:

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

解释:
被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

解题思路

方法:BFS

0.辅助数组:

斜体样式队列q用于BFS;

  • 数组temp存储每次BFS出队后的数据,用于判定边界区域后的恢复;
  • d[x],d[y]用于存储四个方向的步长;
  • 二维数组mask用于设置访问标志,避免重复访问;
  • bianjie用于设置每次BFS的区域是否有处于边界的格子
1.对每个区域使用BFS搜索独立的区域,并将被搜索到的‘O’区域填充为‘X’,同时维护一个访问标志位mask标记每个格子是否被访问过;
2.对每个区域判定是否属于边界,若存在处于边界的格子,则用设置标志位bianjie;
3.对处于边界的区域,还原填充;

代码

class Solution {
public:
    struct Coordinate {
        int x ;
        int y ;
    };

    int row, col;
    
    vector<vector<bool>> mask;
    int dx[4]={-1,0,1,0}, dy[4]={0,-1,0,1};
    bool bianjie = false;

    bool check(vector<vector<char>>& board, int x_new, int y_new) {
        if(x_new>=0 && x_new<row && y_new>=0 && y_new<col) {
            
            if(board[x_new][y_new] == 'O' && !mask[x_new][y_new]){
                if(x_new == 0 || x_new == row-1 || y_new == 0 || y_new == col-1) {
                    bianjie = true;
                }
                return true;
            }
        }
        return false;
    }

    void bfs(vector<vector<char>>& board, queue<Coordinate> &q) {   
        vector<Coordinate> temp ;	//存储每次BFS的数据,用于if(bianjie)处的还原
        while(!q.empty()) {
            Coordinate c = q.front();
            q.pop();
            temp.push_back(c);
            for(int i=0; i<4; i++) {
                int x_new = c.x + dx[i];
                int y_new = c.y + dy[i];
                if(check(board, x_new, y_new)) {
                    q.push({x_new, y_new});
                    board[x_new][y_new] = 'X';
                    mask[x_new][y_new] = true;
                }
            }
        }
        // 如果该次搜索的区域存在边界上的格子,则还原此次操作
        if(bianjie) {
            while(!temp.empty()) {
                Coordinate t = temp.back();
                temp.pop_back();
                board[t.x][t.y] = 'O';
            }
        }
    }

    void solve(vector<vector<char>>& board) {
        row = board.size();
        if(row == 0) {
            return ;
        }
        col = board[0].size();
        mask.assign(row, vector<bool>(col,false));
        int res=0;
        queue<Coordinate > q;
        for(int i=0; i<row; i++) {
            for(int j=0; j<col; j++) {
                bianjie = false;
                if(board[i][j] == 'O' && !mask[i][j])
                {
                    res++;
                    cout<<res<<endl;
                    q.push({i,j});
                    mask[i][j] = true;
                    board[i][j] = 'X';
                    if(i == 0 || i==row-1 || j==0 || j ==col-1) {
                        bianjie = true;
                    }
                    bfs(board, q);
                }  
            }
        }
        return ;
    }
};

//[["O","O"],["O","O"]]
优化:

可以用一个vector实现队列,用位置标记记录队列头尾位置;可以省去使用temp数组
vector q;
读取:c = q.front(); h++;
进队列: q.push_back({i,j}); r++;
判定条件:while(h!=r)

你可能感兴趣的:(leetcode,图,队列,leetcode,算法)