LeetCode 130. Surrounded Regions 并查集/medium


1.Description

给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

2.Example

X X X X
X O O X
X X O X
X O X X

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

3.Solution

类似于803题打砖块;
这一题先将矩阵周围四个边上的‘O’连到一个虚拟的size上(看成是连到墙上),然后对其他的所有砖块进行判断,如果一个砖块是‘O’的话向左看一下,向上看一下,如果左边或者上边还是’O’的话就将这两个连起来。
将所有砖块连完之后,对不在四周四个边上的砖块进行判断,如果一个砖块是‘O’并且没有和size相连,那么就是被包围了,换成‘X’即可。

class Solution {
	
    public void solve(char[][] board) {
        if(board.length==0){
            return;
        }
    	int rows = board.length;
    	int cols = board[0].length;
    	
    	int size = rows*cols;
        UnionFind unionFind = new UnionFind(size+1);
        
        for(int i=0;i<rows;i++) {
        	for(int j=0;j<cols;j++) {
        		if(i==0||i==rows-1||j==0||j==cols-1) {//处理四周的(第一行和最后一行,第一列和最后一列)
        			if(board[i][j]=='O') {//将四周的‘O’都连到一个虚拟的size上
        				unionFind.union(getIndex(i,j,cols), size);//连到size上可看做连到四周墙上
        			}
        		}
        	}
        }
        
        for(int i=1;i<rows;i++) {
        	for(int j=0;j<cols;j++) {
                if (board[i][j] == 'O') {
                    // 如果上方也是砖块
                    if (board[i - 1][j] == 'O') {
                        unionFind.union(getIndex(i - 1, j,cols), getIndex(i, j,cols));
                    }
                    // 如果左边也是砖块
                    if (j > 0 && board[i][j - 1] == 'O') {
                        unionFind.union(getIndex(i, j - 1,cols), getIndex(i, j,cols));
                    }
                }
        	}
        }
        
        for(int i=1;i<rows-1;i++) {
        	for(int j=1;j<cols-1;j++) {
        		if(board[i][j]=='O') {
        			if(!unionFind.isConnected(getIndex(i, j, cols), size)){
            			board[i][j] = 'X';
            		}
        		}
        	}
        }
    }
    
    private int getIndex(int i, int j,int cols) {
		return i*cols+j;
	}

	private class UnionFind{
    	private int[] parent;
        
    	public UnionFind(int n) {
			parent = new int[n];
			for (int i=0;i<n;i++) {
				parent[i]=i;
			}
		}
    	
    	/**
    	 * 路径压缩
    	 */
    	public int find(int x) {
			if(x!=parent[x]) {
				parent[x] = find(parent[x]);
			}
			return parent[x];
		}
    	
    	public void union(int x,int y) {
    		int rootX = find(x);
    		int rootY = find(y);
    		
    		if(rootX == rootY) {
    			return;
    		}
    		parent[rootX] = rootY;
    	}
    	
        public boolean isConnected(int x, int y) {
            return find(x) == find(y);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值