leetcode 130.被围绕的区域

原题

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';
                    }
                }
            }
        }        
    }
}

方法一、方法二参考资料1
方法一、方法二参考资料2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可爱抱抱呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值