题目
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例
输入:
X X X X
X O O X
X X O X
X O X X
运行你的函数后,矩阵变为:
X X X X
X X X X
X X X X
X O X X
解释:
被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的
思路
我们要把被X包围的O变为X,只需要找到与边界相连的O即可,这些O是不需要被改变的。所以我们遍历二维数组的上下左右边界,判断当前元素是否是O,如果是O则进入dfs深度优先遍历,把与此O相连的所有O置为V(此字母可任定,只要不是X与O即可),如果不是,继续遍历即可。当所有遍历完成后,所有与边界相连的O都变为了V,所以剩余的O则是我们需要变为X的O,循环改变即可,最后再把V变回O。
代码
public class problem130 {
static int[][] pos = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
public void solve(char[][] board) {
//特判
if(board.length==0)
return;
// 遍历上下边界
for (int i = 0; i < board[0].length; i++) {
if (board[0][i] == 'O') {
dfs(board, 0, i);
}
if (board[board.length - 1][i] == 'O') {
dfs(board, board.length - 1, i);
}
}
// 遍历左右边界
for (int i = 0; i < board.length; i++) {
if (board[i][0] == 'O') {
dfs(board, i, 0);
}
if (board[i][board[0].length - 1] == 'O') {
dfs(board, i, board[0].length - 1);
}
}
// //打印输出当前board数组
// for (int i = 0; i < board.length; i++) {
// for (int j = 0; j < board[0].length; j++) {
// System.out.print(board[i][j]+" ");
// }
// System.out.println();
// }
// System.out.println();
// dfs后修改内部的'O'
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'O')
board[i][j] = 'X';
else if (board[i][j] == 'V')
board[i][j] = 'O';
}
}
}
//深度优先搜索
public void dfs(char[][] board, int x, int y) {
if(board[x][y]=='O'){
board[x][y]='V';
for(int i=0;i<4;i++){
int newX=x+pos[i][0];
int newY=y+pos[i][1];
//判断索引是否合理
if(newX>=0&&newX<board.length
&&newY>=0&&newY<board[0].length){
dfs(board, newX, newY);
}
}
}
}
public static void main(String[] args) {
problem130 pro = new problem130();
char[][] board = {
{'X','O','X'},{'O','X','O'},{'X','O','X'}
};
pro.solve(board);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
}
}
X O X
O X O
X O X