题目地址:
https://leetcode.com/problems/surrounded-regions/
给定一个二维数组,里面全是
O
O
O或者
X
X
X字符,要求将所有被
X
X
X包围起来的
O
O
O都变为
X
X
X,含边界的包围圈不算。
主要思想是floodfill,只需要对每个位置进行DFS深搜,把所有被
X
X
X包围的
O
O
O都变为
X
X
X即可。由于这里不允许含边界,所以我们可以事先对边界上的
O
O
O进行一遍floodfill,用其他字母比如
#
\#
#标记一下,这样不能变为
X
X
X的所有
O
O
O都已经被标记为
#
\#
#了,接下来再对其余的
O
O
O进行floodfill,最后再把
#
\#
#变回来即可。代码如下:
public class Solution {
public void solve(char[][] board) {
// 判空
if (board == null || board.length == 0 || board[0].length == 0) {
return;
}
int m = board.length, n = board[0].length;
// 储存一下四个方向
int[][] d = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
// 先对首列和尾列上的O进行floodfill,并用#标记
for (int i = 0; i < m; i++) {
if (board[i][0] == 'O') {
dfs(board, i, 0, d, '#');
}
if (board[i][n - 1] == 'O') {
dfs(board, i, n - 1, d, '#');
}
}
// 先对首行和尾行上的O进行floodfill,并用#标记
for (int i = 0; i < n; i++) {
if (board[0][i] == 'O') {
dfs(board, 0, i, d, '#');
}
if (board[m - 1][i] == 'O') {
dfs(board, m - 1, i, d, '#');
}
}
// 接下来对其余的O进行floodfill,变为X。此时剩下的O,一定都是被X包围的了。
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'O') {
dfs(board, i, j, d, 'X');
}
}
}
// 最后再把#还原成O
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == '#') {
board[i][j] = 'O';
}
}
}
}
private void dfs(char[][] board, int x, int y, int[][] d, char mark) {
board[x][y] = mark;
for (int i = 0; i < 4; i++) {
int newX = x + d[i][0];
int newY = y + d[i][1];
// 如果下一步没有出界,并且也是O,则走过去,并进行下一层递归
if (newX >= 0 && newX < board.length && newY >= 0 && newY < board[0].length && board[newX][newY] == 'O') {
dfs(board, newX, newY, d, mark);
}
}
}
}
时空复杂度 O ( m n ) O(mn) O(mn),因为要暴搜整个棋盘,递归栈深度最深也是整个棋盘的规模。