原题
130.被围绕的区域
2020年8月11日 每日一题
题解
矩阵中无非两种字母X或者O。而O分两种,一种是边界上的以及通过O可以连接到边界的,另一种则是无法通过自己或者其他的O连接到边界的O的,我们需要改变的是后一种O,也就是说,可以由每一个边界上的O向四周扩展到所有的外围O,剩下的O改成X。
那么为了标记边界的O,我们每每触及到一个边界O,可把它换为另一个符号,比如临时把O改成A,如此处理完后,再把得到的矩阵,按照A->O以及O->X的方法变换即可。以下的方法一和方法二将会说明实现这个目标的两种途径:
方法一 dfs
新建了一个修改方法bianjie0(char[][] board,int i,int j),此方法是将board矩阵里面(ij处为0)的自身以及相邻的0变为A(每一次执行伴随着对此处周围4个格子继续执行,直到遇到非O格子或者边界为止,因此这是一个多支链式方法),那么我们对矩阵边界上的所有cell执行此方法后,在对得到的中间矩阵进一步处理即可得到答案。
本方法java代码示例:
/*
@v7fgg
执行用时:2 ms, 在所有 Java 提交中击败了98.17%的用户
内存消耗:41.8 MB, 在所有 Java 提交中击败了71.25%的用户
2020年8月1日 11:03
*/
class Solution {
public void solve(char[][] board) {
if(board.length>0){
//首先把与上下左右边界连接的O换成A
for(int i=0;i<board.length;i++){
bianjie0(board,i,0);
bianjie0(board,i,board[0].length-1);
}
for(int j=0;j<board[0].length;j++){
bianjie0(board,0,j);
bianjie0(board,board.length-1,j);
}
//那么此时的O应该是X,A应该是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]=='A'){board[i][j]='O';}
}
}
}
}
public void bianjie0(char[][] board,int i,int j){
//本方法是把O的位置换成A
//出界或者遇见不是O的地方则终止方法
if(i<0||i==board.length||j<0||j==board[0].length||board[i][j]!='O'){
return;
}
board[i][j]='A';
bianjie0(board,i+1,j);
bianjie0(board,i-1,j);
bianjie0(board,i,j+1);
bianjie0(board,i,j-1);
}
}
方法二 bfs
此方法的基本思路和方法一类似,只是实现上和层级的先后有差别,效果一样。
new一个栈,用来存放坐标,初始状态存放所有边界O的坐标,后依次取出坐标,在board中改为B后,拓展四周O的点并放入栈中,以上过程持续到栈空为止。最后再一次处理矩阵board。
本思路java代码示例:
/*
@v7fgg
执行用时:4 ms, 在所有 Java 提交中击败了27.50%的用户
内存消耗:41.6 MB, 在所有 Java 提交中击败了90.96%的用户
2020年8月11日 16:03
*/
class Solution {
public void solve(char[][] board) {
if(board.length>0){
int fangxiang[][]=new int[][]{{0,-1},{0,1},{-1,0},{1,0}};
Stack<int[]> stack=new Stack<>();
for(int i=0;i<board.length;i++){
if(board[i][0]=='O'){
stack.push(new int[]{i,0});
}
if(board[i][board[0].length-1]=='O'){
stack.push(new int[]{i,board[0].length-1});
}
}
for(int j=1;j<board[0].length-1;j++){
if(board[0][j]=='O'){
stack.push(new int[]{0,j});
}
if(board[board.length-1][j]=='O'){
stack.push(new int[]{board.length-1,j});
}
}
while(!stack.isEmpty()){
int[] a=stack.pop();
board[a[0]][a[1]]='B';
for(int i=0;i<4;i++){
int x=a[0]+fangxiang[i][0];
int y=a[1]+fangxiang[i][1];
if(x>=0&&x<board.length&&y>=0&&y<board[0].length&&board[x][y]=='O'){
stack.push(new int[]{x,y});
}
}
}
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++){
if(board[i][j]=='B'){
board[i][j]='O';
}
else if(board[i][j]=='O'){
board[i][j]='X';
}
}
}
}
}
}