130. Surrounded Regions

本文介绍一种算法,用于在二维棋盘中捕获被X包围的所有O型区域,并将其转换为X。通过从边缘的O开始进行广度优先搜索(BFS),标记与边缘连通的所有O,然后将未标记的O转换为X。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region .

For example,

X X X X
X O O X
X X O X
X O X X

 

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

分析:先找到边缘的O,与边缘的O连通的所有O均不用转化成X(这里连通的意思是从边缘的O开始有一条全是O的路径可以到达该点),其他的所有O都变成X。我们只要从边缘的O开始bfs标记所有与它连通的O,然后再把所有未标记的O变成X。

下面的代码中是使用了一个标记数组。如果想节省空间,可以先把与边缘O连通的O先变成#,然后再把剩余的O变为X,再把#变成O。 

class Solution {
public:
    struct Qnode
    {
        int i_;
        int j_;
        Qnode(int x,int y):i_(x),j_(y){};
        Qnode(){};
    };
    void solve(vector<vector<char>> &board) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        int row = board.size();
        if(row == 0)return;
        int colum = board[0].size();
        queue<Qnode> myqueue;
        bool visited[row][colum];
        memset(visited, 0, sizeof(visited));
        //首先标记所有没有被包围的O
        for(int i = 0; i < row; i++)
        {
            for(int j = 0; j < colum; j++)
            {//首先找到四周的O,和这个O连成一片的O都不用转换
                if(i == 0 || i == row - 1 || j == 0 || j == colum - 1)
                    if(visited[i][j] == false && board[i][j] == 'O')
                        {
                            visited[i][j] = true;
                            myqueue.push(Qnode(i,j));
                            while(myqueue.empty() == false)
                            {
                                Qnode tmp = myqueue.front();
                                myqueue.pop();
                                //board[tmp.i_][tmp.j_] = 'X';
                                if(tmp.i_-1>=0 && board[tmp.i_-1][tmp.j_] == 'O'
                                    &&visited[tmp.i_-1][tmp.j_] == false)
                                {//上
                                    visited[tmp.i_-1][tmp.j_] = true;
                                    myqueue.push(Qnode(tmp.i_-1, tmp.j_));
                                }
                                if(tmp.i_+1 < row && board[tmp.i_+1][tmp.j_] == 'O'
                                    &&visited[tmp.i_+1][tmp.j_] == false)
                                {//下
                                    visited[tmp.i_+1][tmp.j_] = true;
                                    myqueue.push(Qnode(tmp.i_+1, tmp.j_));
                                }
                                if(tmp.j_-1 >= 0 && board[tmp.i_][tmp.j_-1] == 'O'
                                    &&visited[tmp.i_][tmp.j_-1] == false)
                                {//左
                                    visited[tmp.i_][tmp.j_-1] = true;
                                    myqueue.push(Qnode(tmp.i_, tmp.j_-1));
                                }
                                if(tmp.j_+1 < colum && board[tmp.i_][tmp.j_+1] == 'O'
                                    &&visited[tmp.i_][tmp.j_+1] == false)
                                {//右
                                    visited[tmp.i_][tmp.j_+1] = true;
                                    myqueue.push(Qnode(tmp.i_, tmp.j_+1));
                                }
                            }
                        }
            }
        }
        //把未被标记的O转换成X
        for(int i = 0; i < row; i++)
            for(int j = 0; j < colum; j++)
                if(board[i][j] == 'O' && visited[i][j] == false)
                    board[i][j] = 'X';
        
    }
};

2015.9.16更新

----------------------

这道题我一开始是这样做的。如下。但是我发现当遇到稍微大一些的char矩阵时,算法便会TLE。我是百思不得其解啊,不知道哪里写得有问题。后来,我把自己的程序与tenos的程序进行比较,发现仅仅有稍微的不同,而这稍微的不同,恰恰是我的代码TLE的原因。

我的代码使用了bfs,当PPoint从queue中出来时,我将这个PPiont代表的字符赋值为'#'。而这种做法恰恰导致了我的算法会TLE。

设想在bfs深度为n时,有A和B两个点,A点和B点都和C点相邻。并且这三个点的字符值都为'O',假设A先出queue,这个时候把A代表的字符赋值为'#',并把C加入队列。接着B出queue,这个时候把C加入队列。看到没有,如果在出队列时,才把字符赋值为'#'的话,我们会把同一个PPoint多次加入到queue中!!!!当字符矩阵比较大时,这会大大拖慢速度!!!正确的做法是什么呢,一旦知道某个点满足条件,马上将此点赋值为'#'!!!!! 见最下面的代码:

class Solution {
private:
    struct PPoint{
        int row;
        int col;
        PPoint(int r, int c):row(r), col(c) {}
    };

    void helper(vector<vector<char>>& board, int row, int col) {
        PPoint p(row, col);
        
        queue<PPoint> q;
        q.push(p);
        int m = (int)board.size(), n = (int)board[0].size();
        while (!q.empty()) {
            PPoint& front = q.front();
            int row = front.row, col = front.col;
            board[row][col] = '#';
            q.pop();
            if (row>=1&&board[row-1][col]=='O') {
                
                q.push(PPoint(row-1, col));
            }
            if (row+1<=m-1&&board[row+1][col]=='O') {
                q.push(PPoint(row+1, col));
            }
            if (col>=1&&board[row][col-1]=='O') {
                q.push(PPoint(row, col-1));
            }
            if (col+1<=n-1&&board[row][col+1]=='O') {
                q.push(PPoint(row, col+1));
            }
        }
        
        
    }
public:
    void solve(vector<vector<char>>& board) {
        int m = (int)board.size();
        if (m==0) {
            return;
        }
        int n = (int)board[0].size();
        for (int i=0; i<n; i++) {
            if (board[0][i]=='O') {
                helper(board, 0, i);
            }
            if (board[m-1][i]=='O') {
            
                helper(board, m-1, i);
            }
        }
        for (int i=0; i<m; i++) {
            if (board[i][0]=='O') {
                helper(board, i, 0);
            }
            if (board[i][n-1]=='O') {
                
                helper(board, i, n-1);
            }
        }
        for (int i=0; i<m; i++) {
            for (int j=0; j<n; j++) {
                if (board[i][j]=='#') {
                    board[i][j]='O';
                } else if (board[i][j]=='O') {
                    board[i][j]='X';
                }
                
            }
        }
        ;
    }
};

class Solution {
private:
    struct PPoint{
        int row;
        int col;
        PPoint(int r, int c):row(r), col(c) {}
    };

    void helper(vector<vector<char>>& board, int row, int col) {
        PPoint p(row, col);
        board[row][col] = '#';
        queue<PPoint> q;
        q.push(p);
        int m = (int)board.size(), n = (int)board[0].size();
        while (!q.empty()) {
            PPoint& front = q.front();
            int row = front.row, col = front.col;
            q.pop();
            if (row>=1&&board[row-1][col]=='O') {
                board[row-1][col] = '#';
                q.push(PPoint(row-1, col));
            }
            if (row+1<=m-1&&board[row+1][col]=='O') {
                board[row+1][col] = '#';
                q.push(PPoint(row+1, col));
            }
            if (col>=1&&board[row][col-1]=='O') {
                board[row][col-1] = '#';
                q.push(PPoint(row, col-1));
            }
            if (col+1<=n-1&&board[row][col+1]=='O') {
                board[row][col+1] = '#';
                q.push(PPoint(row, col+1));
            }
        }
        
        
    }
public:
    void solve(vector<vector<char>>& board) {
        int m = (int)board.size();
        if (m==0) {
            return;
        }
        int n = (int)board[0].size();
        for (int i=0; i<n; i++) {
            if (board[0][i]=='O') {
                helper(board, 0, i);
            }
            if (board[m-1][i]=='O') {
            
                helper(board, m-1, i);
            }
        }
        for (int i=0; i<m; i++) {
            if (board[i][0]=='O') {
                helper(board, i, 0);
            }
            if (board[i][n-1]=='O') {
                
                helper(board, i, n-1);
            }
        }
        for (int i=0; i<m; i++) {
            for (int j=0; j<n; j++) {
                if (board[i][j]=='#') {
                    board[i][j]='O';
                } else if (board[i][j]=='O') {
                    board[i][j]='X';
                }
                
            }
        }
        ;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值