1. 题目
2. 题意
图形中有两类字符,'X'
,‘O’
两种字符,如果 O
被 X
包围住,则需要将 O
转为 X
。
3. 思路
我们需要将被包围住的 O
去除,这个其实比较麻烦,因为需要确实四周都是 X
,这里采用一个相反的思路,即我们将不被包含的字符 O 进行标记,剩余没有被标记的 O,全部置为 X 即可
。
而我们如何确定字符 O 没有被包围?我们通过观察,可以知道,与边有接触的 O,即为不被包围的 O。因此,我们可以考虑遍历所有边上 O,按照 DFS 的思路,将所有与边上的 O 接触的 O进行标记。
4. 解题代码
public void solve(char[][] board) {
if (board == null || board.length == 0 || board[0].length == 0) {
return;
}
// 用于标记 O 是否被包围,true 代表不被包围,即可以保留
boolean[][] check = new boolean[board.length][board[0].length];
// 对四条边上的字符进行遍历
for (int i = 0; i < board[0].length; i++) {
helper(board, check, 0, i);
helper(board, check, board.length - 1, i);
}
for (int i = 1; i < board.length - 1; i++) {
helper(board, check, i, 0);
helper(board, check, i, board[0].length - 1);
}
// 遍历所有字符,将所有没有被标记的 O,转为 X
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'O' && !check[i][j]) {
board[i][j] = 'X';
}
}
}
}
private void helper(char[][] board, boolean[][] check, int i, int j) {
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] == 'X' || check[i][j]) {
return;
}
check[i][j] = true;
helper(board, check, i + 1, j);
helper(board, check, i - 1, j);
helper(board, check, i, j + 1);
helper(board, check, i, j - 1);
}