给定一个二维的矩阵,包含 ‘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
最开始我以为这道题是动态规划,但我改算法改了好久都不能AC,搞得到我整天都很郁闷,最后才发现这道题是图的搜索问题——BFS和DFS,瞬间豁然开朗。这道题的突破口在于矩阵的边界,我们只要找到了矩阵边界的“O”,然后从矩阵边界的“O”开始向矩阵内部搜索与其接壤的“O”,将所有与边界“O”接壤的“O”进行标记,在通过一次遍历将矩阵中所有被标记的“O”改为“X”即可。
题解(一):DFS
递归写法(我个人其实不是很喜欢递归写法,总给人一种代码不安全的感觉)
class Solution {
public void solve(char[][] board) {
if(board.length==0||board[0].length==0)
return;
int rowLength= board[0].length;
int columnLength= board.length;
for(int i=0;i<rowLength;i++){
DFS(board,0,i);
DFS(board,columnLength-1,i);
}
for(int j=1;j<columnLength-1;j++){
DFS(board,j,0);
DFS(board,j,rowLength-1);
}
for(int i=0;i<columnLength;i++)
for(int j=0;j<rowLength;j++){
if(board[i][j]=='*')
board[i][j]='O';
else if(board[i][j]=='O')
board[i][j]='X';
}
}
private void DFS(char[][]board,int i,int j){
if(i<0||i>=board.length||j<0||j>= board[0].length)
return;
if(board[i][j]=='*'||board[i][j]=='X')
return;
board[i][j]='*';
DFS(board,i+1,j);
DFS(board,i-1,j);
DFS(board,i,j-1);
DFS(board,i,j+1);
}
}
非递归写法,利用栈实现
import java.util.*;
class Solution {
public void solve(char[][] board) {
if (board.length == 0 || board[0].length == 0)
return;
int rowLength = board[0].length;
int columnLength = board.length;
for (int i = 0; i < rowLength; i++) {
DFS(board, 0, i);
DFS(board, columnLength - 1, i);
}
for (int j = 1; j < columnLength - 1; j++) {
DFS(board, j, 0);
DFS(board, j, rowLength - 1);
}
for (int i = 0; i < columnLength; i++)
for (int j = 0; j < rowLength; j++) {
if (board[i][j] == '*')
board[i][j] = 'O';
else if (board[i][j] == 'O')
board[i][j] = 'X';
}
}
/*
* direction:
* 1.up
* 2.down
* 3.left
* 4.right
*/
private void DFS(char[][] board, int i, int j) {
if(board[i][j]=='X'||board[i][j]=='*')
return;
board[i][j]='*';
int rowLength = board[0].length;
int columnLength = board.length;
HashMap<int[], Integer> direction = new HashMap<>();
Stack<int[]> move = new Stack<>();
move.push(new int[]{
i, j});
while (!move.isEmpty()) {
int[] tempArray = move.peek();
int m = tempArray[0];
int n = tempArray[1];
int temp = direction.getOrDefault( tempArray, 1);
direction.put( tempArray, temp + 1);
if (temp == 1) {
if (m - 1 >= 0 && board[m - 1][n] == 'O') {
board[m - 1][n] = '*';
move.push(new int[]{
m - 1, n});
}
} else if (temp == 2) {
if (m + 1 <= columnLength - 1 && board[m + 1][n] == 'O') {
board[m + 1][n] = '*';
move.push(new int[]{
m + 1, n});
}
} else if (temp == 3) {
if (n - 1 >= 0 && board[m][n - 1] == 'O') {
board[m][n - 1] = '*';
move.push(new int[]{
m, n - 1});
}
} else if (temp == 4) {
if (n + 1 <= rowLength - 1 && board[m][n + 1] == 'O') {
board[m][n + 1] = '*';
move.push(new int[]{
m, n + 1});
}
} else if (temp == 5) {
move.pop();
}
}
}
}
题解(二):BFS(队列实现)
import java.util.*;
class Solution {
public void solve(char[][] board) {
Queue<int[]>check=new LinkedList<>();
if(board.length==0||board[0].length==0)
return;
int rowLength= board[0].length;
int columnLength= board.length;
for(int i=0;i<rowLength;i++){
if(board[0][i]=='O') {
check.offer(new int[]{
0,i});
board[0][i]='*';
}
if(board[columnLength-1][i]=='O') {
check.offer(new int[]{
columnLength-1,i});
board[columnLength-1][i]='*';
}
}
for(int i=1;i<columnLength-1;i++) {
if (board[i][0] == 'O') {
check.offer(new int[]{
i,0});
board[i][0] = '*';
}
if (board[i][rowLength - 1] == 'O') {
check.offer(new int[]{
i,rowLength-1});
board[i][rowLength - 1] = '*';
}
}
while(!check.isEmpty()){
int[]temp=check.poll();
int i=temp[0];
int j=temp[1];
if(j+1<=rowLength-1&&board[i][j+1]=='O') {
check.offer(new int[]{
i,j+1});
board[i][j+1]='*';
}
if(j-1>=0&&board[i][j-1]=='O'){
check.offer(new int[]{
i,j-1});
board[i][j-1]='*';
}
if(i-1>=0&&board[i-1][j]=='O'){
check.offer(new int[]{
i-1,j});
board[i-1][j]='*';
}
if(i+1<=columnLength-1&&board[i+1][j]=='O'){
check.offer(new int[]{
i+1,j});
board[i+1][j]='*';
}
}
for(int i=0;i<columnLength;i++)
for(int j=0;j<rowLength;j++){
if(board[i][j]=='*')
board[i][j]='O';
else if(board[i][j]=='O')
board[i][j]='X';
}
}
}