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';
}
}
}
;
}
};