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