题目描述:
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第一反应想到的方法是通过DFS递归来实现,代码如下(使用了一个新的vector来记录该点有没有走过,实际上有更简单的方法,将走过的值改为另一个字符,比如'V'来作为标记即可):
class Solution {
public:
int N;
void solve(vector<vector<char>> &board)
{
vector<vector<bool>> mark;
N = board.size();
for (int i = 0; i < N; i++)
{
vector<bool> line(board.size(), false);
mark.push_back(line);
}
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
if (board[i][j] == 'O'&&!mark[i][j])
cover(mark, board, i, j);
}
}
bool cover(vector<vector<bool>> &mark, vector<vector<char>> &board, int currX, int currY)
{
if (board[currX][currY] == 'X')
return true;
if (mark[currX][currY])
return false;
cout << currX << " " << currY << "\r\n";
//确定四个方向的点
int x[4], y[4];
x[0] = currX;
y[0] = currY - 1;
x[1] = currX;
y[1] = currY + 1;
x[2] = currX - 1;
y[2] = currY;
x[3] = currX + 1;
y[3] = currY;
mark[currX][currY] = true;
if (currX == 0 || currX == N - 1 || currY == 0 || currY == N - 1)
return false;
for (int i = 0; i < 4; i++)
{
if (x[i] >= 0 && x[i] < N && y[i] >= 0 && y[i] < N && mark[x[i]][y[i]])
continue;
if (x[i] >= N || y[i] >= N || x[i] < 0 || y[i] < 0 || !cover(mark, board, x[i], y[i]))
return false;
}
board[currX][currY] = 'X';
return true;
}
};
但是当遇到大规模矩阵时用DFS会出现stack overflow,因此考虑使用BFS来实现。
判定一个'O'是否被'X'只需看O是否能走到边界,因此通过BFS找出所有与边界线上的O相连的O即可,其余O全部翻为X。代码如下:
class Solution {
public:
int row, col;
queue<int> bfs;
void solve(vector<vector<char>> &board)
{
if (board.empty())
return;
row = board.size();
col = board[0].size();
for (int i = 0; i < col; i++)
{
//上边
if (board[0][i] == 'O')
BFS(board, i);
//下边
if (board[row - 1][i] == 'O')
BFS(board, (row - 1)*col + i);
}
for (int i = 0; i < row; i++)
{
//左边
if (board[i][0] == 'O')
BFS(board, i*col);
//右边
if (board[i][col - 1] == 'O')
BFS(board, i*col + col - 1);
}
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
{
if (board[i][j] == 'O')
board[i][j] = 'X';
if (board[i][j] == 'V')
board[i][j] = 'O';
}
}
void BFS(vector<vector<char>> &board, int index)
{
board[index / col][index % col] = 'V';
bfs.push(index);
while (!bfs.empty())
{
int ind = bfs.front();
bfs.pop();
int x = ind / col;
int y = ind % col;
//tips:会导致大量重复操作
//board[x][y] = 'V';
if (x - 1 >= 0 && board[x - 1][y] == 'O')
{
board[x - 1][y] = 'V';
bfs.push((x - 1)*col + y);
}
if (x + 1 < row&&board[x + 1][y] == 'O')
{
board[x + 1][y] = 'V';
bfs.push((x + 1)*col + y);
}
if (y - 1 >= 0 && board[x][y - 1] == 'O')
{
board[x][y - 1] = 'V';
bfs.push(x*col + y - 1);
}
if (y + 1 < col&&board[x][y + 1] == 'O')
{
board[x][y + 1] = 'V';
bfs.push(x*col + y + 1);
}
}
}
};
需要注意的一点是:将O标记为V的操作应当在插入queue之前就进行,否则会影响下次循环的判定导致大量重复操作!