- 描述
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.
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
- 思路
这道题可以使用逆向思维进行思考,即求出哪些位置是没有被X包围的O。如果求没有被包围的O,那么可以从矩形的四条边开始考虑,由于这四条边上所有的O都是没有被包围的,如果和这条O相邻,那么该相邻的O也是没有被包围的。可以使用递归的方式判断上下左右相邻的O.为了记录这些没有被包围的O,可以使用一个与bool类型的矩阵记录。代码见下 - 代码(c#)
public void Solve(char[,] board)
{
int row = (int)board.GetLongLength(0);
int col = (int)board.GetLongLength(1);
bool[,] isOk = new bool[row, col];//记录该位置是否被包围
for (int i = 0; i < row; )//判断矩形的上下两条边上的O字母
{
for (int j = 0; j < col; j++)
{
if (board[i, j] == 'O' && !isOk[i, j])
Solve(board, i, j, col, row, isOk);
}
if (i == row - 1) break;
i = row - 1;
}
for (int i = 0; i < col;)//判断矩形左右两条边的O字母
{
for (int j = 0; j < row; j++)
{
if (board[j, i] == 'O' && !isOk[j, i])//如果该位置字母为O并且没有被访问过
Solve(board, j, i, col, row, isOk);
}
if (i == col-1) break;
i = col - 1;
}
for (int i = 1; i < row-1; i++)
{
for (int j = 1; j < col-1; j++)
{
if (!isOk[i, j])//将所有被包围的位置置为X
{
board[i, j] = 'X';
}
}
}
}
public void Solve(char[,] board, int i, int j, int col, int row, bool[,] isOk)
{
isOk[i, j] = true;
if (i - 1 >= 0 && board[i - 1, j] == 'O' && !isOk[i - 1, j])
{
Solve(board, i - 1, j, col, row, isOk);//该位置的上面也没有被X包围
}
if (j + 1 < col && board[i, j + 1] == 'O' && !isOk[i, j + 1])
{
Solve(board, i, j + 1, col, row, isOk);//该位置的右面也没有被X包围
}
if (i + 1 < row && board[i + 1, j] == 'O' && !isOk[i + 1, j])
{
Solve(board, i + 1, j, col, row, isOk);//该位置的下面也没有被X包围
}
if (j - 1 >= 0 && board[i, j - 1] == 'O' && !isOk[i, j - 1])
{
Solve(board, i, j - 1, col, row, isOk);//该位置的左面也没有被X包围
}
}
- 总结
该问题其实我使用正面的思路去尝试解决过,即找出所有被包围的字母,但发现并不容易实现。所以这里使用逆向的思维去求解,反而更容易实现。在问题无法正面解决的时候,可以尝试使用反向的思维去考虑。