被围绕的区域

 被围绕的区域

给一个二维的矩阵,包含 'X' 和 'O', 找到所有被 'X' 围绕的区域,并用 '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
X O X X

class UnionFind{
private:
    unordered_map<int, int> father;
public:
    UnionFind(int n, int m){
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                int id = i * m + j;
                father[id] = id;
            }
        }
    }
    int find(int id){
        int parent = id;
        while(parent != father[parent]){
            parent = father[parent];
        }
        return parent;
    }
    int compress_find(int id){
        int parent = id;
        while(parent != father[parent]){
            parent = father[parent];
        }
        
        int fa = id;
        while(fa != father[fa]){
            int tmp = father[fa];
            father[fa] = parent;
            fa = tmp;
        }
        
        return parent;
    }
    void union_both(int a, int b){
        int fa_a = compress_find(a);
        int fa_b = compress_find(b);
        if(fa_a != fa_b){
            father[fa_a] = father[fa_b];
        }
    }
};
class Solution {
public:
    /**
     * @param board a 2D board containing 'X' and 'O'
     * @return void
     */
    // V1 
    //思路:目标是要找到由X包围起来的O的区域。
    // 首先,外围一圈上的O肯定会保留下来。然后,从外围的O能达到的O也要保留。剩下其他的O就是内部的O。
    // 所以方法就是从外围的一圈进行DFS算法:依次对外圈的“O”做DFS,将其可以到达O临时设置为#。
    void surroundedRegions1(vector<vector<char>>& board) {
        // Write your code here
        if(board.size() == 0 || board[0].size() == 0)
            return;
        
        fillBoarder(board, 'O', '#');
        replace(board, 'O', 'X');
        fillBoarder(board, '#', 'O');
    }
    
    // BFS
    void fillBoarder(vector<vector<char>>& board, char patten, char c){
        int n = board.size();
        int m = board[0].size();
        queue<pair<int,int> > q;//save thoese with patten
        
        // set those boarder pattern with c
        for(int i = 0; i < board.size(); i++){
            if(board[i][0] == patten){
                board[i][0] = c;
                q.push(make_pair(i, 0));
            }
            if(board[i][m-1] == patten){
                board[i][m-1] = c;
                q.push(make_pair(i, m-1));
            }
        }
        for(int j = 1; j < m-1; j++){
            if(board[0][j] == patten){
                board[0][j] = c;
                q.push(make_pair(0, j));
            }
            if(board[n-1][j] == patten){
                board[n-1][j] = c;
                q.push(make_pair(n-1, j));
            }
        }
        
        int dx[4] = {-1, 1, 0, 0};
        int dy[4] = {0, 0, -1, 1};
        while(!q.empty()){
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for(int k = 0; k < 4; k++){
                int nx = x + dx[k];
                int ny = y + dy[k];
                if(nx >= 0 && nx < n && ny >= 0 && ny < m && board[nx][ny] == patten){
                    board[nx][ny] = c;
                    q.push(make_pair(nx, ny));
                }
            }
        }
    }
    
    void replace(vector<vector<char>>& board, char patten, char c){
        for(int i = 0; i < board.size(); i++){
            for(int j = 0; j < board[0].size(); j++){
                if(board[i][j] == patten){
                    board[i][j] = c;
                }
            }
        }
    }
    
    // V2 类似于V1, but use DFS
    void surroundedRegions(vector<vector<char>>& board) {
        // Write your code here
        if(board.size() == 0 || board[0].size() == 0)
            return;
        
        fillBoarderDFS(board, 'O', '#');
        replace(board, 'O', 'X');
        fillBoarderDFS(board, '#', 'O');
    }
    // DFS 
    void fillBoarderDFS(vector<vector<char>>& board, char patten, char c){
        int n = board.size();
        int m = board[0].size();
         
        // set those boarder pattern with c
        for(int i = 0; i < board.size(); i++){
            fillDFS(board, i, 0, patten, c);
            fillDFS(board, i, m-1, patten, c);
        }
        for(int j = 1; j < m-1; j++){
            fillDFS(board, 0, j, patten, c);
            fillDFS(board, n-1, j, patten, c);
        }
    }
    void fillDFS(vector<vector<char>>& board, int x, int y, char patten, char c){
        if(board[x][y] != patten){
            return;
        }
        board[x][y] = c;
        int n = board.size();
        int m = board[0].size();

        // set those boarder pattern with c
        int dx[4] = {-1, 1, 0, 0};
        int dy[4] = {0, 0, -1, 1};
        for(int k = 0; k < 4; k++){
            int nx = x + dx[k];
            int ny = y + dy[k];
            if(nx >= 0 && nx < n && ny >= 0 && ny < m){
                fillDFS(board, nx, ny, patten, c);
            }
            
        }
    }
    ///
    // V3 : Uinon Find
    void surroundedRegions3(vector<vector<char>>& board) {
        if(board.size() == 0 || board[0].size() == 0)
            return;
        int n = board.size();
        int m = board[0].size();
        UnionFind uf(n, m);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                int dx[4] = {-1, 1, 0, 0};
                int dy[4] = {0, 0, -1, 1};
                for(int k = 0; k < 4; k++){
                    int nx = i + dx[k];
                    int ny = j + dy[k];
                    if(nx >= 0 && nx < n && ny >= 0 && ny < m && board[nx][ny] == board[i][j]){
                        int id = i * m + j;
                        int nid = nx * m + ny;
                        uf.union_both(id, nid);
                    }
                }
            }
        }
        // 将边角以及与其相邻的‘O’ 的father 加入set
        unordered_set<int> set;
        for(int i = 0; i < n; i++){
            if(board[i][0] == 'O'){
                int fa = uf.compress_find(i*m);
                set.insert(fa);
            }
            if(board[i][m-1] == 'O'){
                int fa = uf.compress_find(i * m + m - 1);
                set.insert(fa);
            }
        }
        for(int j = 1; j < m-1; j++){
            if(board[0][j] == 'O'){
                int fa = uf.compress_find(j);
                set.insert(fa);
            }
            if(board[n-1][j] == 'O'){
                int fa = uf.compress_find((n-1)*m + j);
                set.insert(fa);
            }
        }
        // 判断是否和边角的‘O’同一个group
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                int fa = uf.find(i * m + j);
                if(board[i][j] == 'O' && set.find(fa) == set.end()){
                    board[i][j] = 'X';
                }
            }
        }
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值