Given a 2D board containing 'X'
and 'O'
(the letter O), capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
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
Explanation:
Surrounded regions shouldn’t be on the border, which means that any 'O'
on the border of the board are not flipped to 'X'
. Any 'O'
that is not on the border and it is not connected to an 'O'
on the border will be flipped to 'X'
. Two cells are connected if they are adjacent cells connected horizontally or vertically.
思路:
题干的意思是将被 X 包围的 O 转换为 X,但是我们可以转换一下角度:找边沿上 O 的4连通区域。连通区域是图像处理中的概念,下面即为4连通区域的简单表示,中心 1 的4连通区域是其上下左右的4个 1 。
0 1 0
1 1 1
0 1 0
在确认连通区域时使用到了计算机图像学中的常用算法:FloodFill。这个算法可以看作是染色操作:将满足条件的区域染色,即转换为另一种颜色,曾经流行的扫雷游戏就是用的这个算法。在此题中并没有让我们将 O 转换为另一种颜色,而是选择是否保留 O ,所以我们先将需要保留的 O 转换为另一任意字符,此处我们用 # 来标记需要保留的 O。最后将 # 转换为 O。
void floodFill(vector<vector<char>> &board, int row, int col){
if (board[row][col] != 'O') return;
int highth = board.size(), width = board[0].size();
queue<vector<int>> BFS;
BFS.push({ row, col });
board[row][col] = '#';
while (!BFS.empty()){
vector<int> coor = BFS.front();
BFS.pop();
int r = coor[0], c = coor[1];
if (r > 0 && board[r - 1][c] == 'O'){
BFS.push({ r - 1, c });
board[r - 1][c] = '#';
}
if (r < highth - 1 && board[r + 1][c] == 'O'){
BFS.push({ r + 1, c });
board[r + 1][c] = '#';
}
if (c > 0 && board[r][c - 1] == 'O'){
BFS.push({ r, c - 1 });
board[r][c - 1] = '#';
}
if (c < width && board[r][c + 1] == 'O'){
BFS.push({ r, c + 1 });
board[r][c + 1] = '#';
}
}
}
void solve(vector<vector<char>>& board) {
if (int(board.size()) <= 1 || int(board[0].size()) <= 0) return;
int highth = board.size(), width = board[0].size();
// 从board的四周进行FloodFill
for (int i = 0; i < highth; i++){
floodFill(board, i, 0);
floodFill(board, i, width - 1);
}
for (int j = 0; j < width; j++){
floodFill(board, 0, j);
floodFill(board, highth - 1, j);
}
// 将原先记录的'#'转换为'O'
for (int i = 0; i < highth; i++){
for (int j = 0; j < width; j++){
if (board[i][j] == '#')
board[i][j] = 'O';
else board[i][j] = 'X';
}
}
}
最后,非常感谢Code Ganker的分享。