Leetcode-130. 被围绕的区域

130. 被围绕的区域
给定一个二维的矩阵,包含 '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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
运行结果
图片说明
解题思路
利用并查集的思想
将所有边缘上的O的父亲置为虚拟节点dimon
然后遍历其他的O,如果将其与其四周的O连通----使得与边缘的O相连的O的父亲也是dimon
这样再次遍历,只要父亲不是虚拟节点的O均置为X
java代码

class Solution {
    public void solve(char[][] board) {
        int m=board.length;
        if(m == 0) return;
        int n=board[0].length;
        UF uf=new UF(m*n+1);
        int domin=m*n;
        //左右边界的0和虚拟节点合并
        for(int i=0;i<m;i++){
            if(board[i][0]=='O'){
                uf.union(i*n,domin);
            }
            if(board[i][n-1]=='O'){
                uf.union(i*n+n-1,domin);
            }
        }
        //上下边界的0和虚拟节点合并
        for(int i=0;i<n;i++){
            if(board[0][i]=='O'){
                uf.union(i,domin);
            }
            if(board[m-1][i]=='O'){
                uf.union(n*(m-1)+i,domin);
            }
        }
        // 方向数组 d 是上下左右搜索的常用手法
        int[][] d = new int[][]{{1,0}, {0,1}, {0,-1}, {-1,0}};
        for(int i=1;i<m-1;i++){
            for(int j=1;j<n-1;j++){
                if(board[i][j]=='O'){
                    //将其与四周的O连通
                    for(int k=0;k<4;k++){
                        int x=i+d[k][0];
                        int y=j+d[k][1];
                        if(board[x][y]=='O'){
                            uf.union(x*n+y,i*n+j);
                        }
                    }
                }
            }
        }
        // 所有不和 dummy 连通的 O,都要被替换
        for(int i=1;i<m-1;i++){
            for(int j=1;j<n-1;j++){
                if(board[i][j]=='O' &&!uf.getconnected(i*n+j,domin)){
                    board[i][j]='X';
                }
            }
        }
    }
    class UF{
        private int[] parent;
        private int[] size;
        private int count;

        public UF(int n){
            parent=new int[n];
            size=new int[n];
            count=n;
            for(int i=0;i<n;i++){
                parent[i]=i;
                size[i]=1;
            }
        }

        public void union(int a,int b){
            int roota=find(a);
            int rootb=find(b);
            if(roota == rootb) return;
            if(size[roota]>size[rootb]){
                parent[rootb]=roota;
                size[roota]+=size[rootb];
            }
            else{
                parent[roota]=rootb;
                size[rootb]+=size[roota];
            }
        }

        public int find(int x){
            while(parent[x] != x){
                parent[x]=parent[parent[x]];
                x=parent[x];
            }
            return x;
        }

        public boolean getconnected(int a,int b){
            int roota=find(a);
            int rootb=find(b);
            return roota==rootb;
        }

        public int getcount(){
            return count;
        }
    }
}
Leetcode-牛客-刷题笔记 文章被收录于专栏

本专栏主要用于分享栏主在准备java后端面试过程中的刷题笔记

全部评论

相关推荐

今年读完研的我无房无车无对象,月入还没有过万&nbsp;看到他在朋友圈晒房产证,感叹自己白读了这么多年书
梦想是成为七海千秋:那咋了,双9毕业的现在还没存款呢(因为没念完),高中毕业的去直播带货月入几百万也是完全有可能的,退一万步讲,有些人刚出生父母就给买车买房了,上哪说理去,哪怕是同一个起点也会有截然不同的走向,过好自己的生活就完事了。
点赞 评论 收藏
分享
05-09 13:22
门头沟学院 Java
点赞 评论 收藏
分享
06-06 03:40
已编辑
电子科技大学 Java
在秋招的小白菜很想养修勾:一眼 苍穹外卖+谷粒商城,项目换一换吧,可以找一些付费知识星球博主带带,避免烂大街。多投投大厂,背背八股,你这学历乱杀了,等实习经验到位,到时候大厂闭眼选
投递美团等公司8个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务