Given a 2D board containing 'X'
and 'O'
, capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
For 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
题目的意思就是被 'X' 围起来的 'O' 符号要被处理为 ‘X’ 符号,因此可以把O符号进行分类,然后在遍历的过程中进行合并操作,采用并查集的数据结构。初步代码如下,只是采用了比较简单的并查集,并使用路径压缩进行优化,还可以继续对合并操作进行改进,降低运行时间。
public class SurroundedRegions {
private class UnionFind{
int[] arr;
public UnionFind(int len){
arr = new int[len];
for(int i=0; i<len; i++)
arr[i] = i;
}
/**
* 合并,root1所属集合并入root2所属集合
* @param root1
* @param root2
*/
public void union(int root1, int root2){
//先找到双方的根序号
int s1 = find(root1);
int s2 = find(root2);
arr[s1] = arr[s2];
}
/**
* 返回root编号
* @param el
* @return
*/
public int find(int el){
if(arr[el] == el)
return el;
else{
//路径压缩
arr[el] = find(arr[el]);
return arr[el];
}
}
}
public void solve(char[][] board) {
if(board == null || board.length == 0 || board[0].length == 0)
return;
int height = board.length;
int width = board[0].length;
UnionFind uf = new UnionFind(height * width + 1);
int len = height * width;
//不需要编号的集合编号为 height * width
for(int i=0; i<height; i++) {
for(int j=0; j<width; j++){
char c = board[i][j];
if(c == 'O'){
//边上的点直接并入height * width
if(i == 0 || i == height-1 || j == 0 || j == width-1){
uf.union(i * width + j, len);
if(i > 0 && board[i-1][j] == 'O')
uf.union((i-1) * width + j, len);
if(j > 0 && board[i][j-1] == 'O')
uf.union(i * width + j - 1, len);
}
else{
if(board[i-1][j] == 'O'){
if(uf.find((i-1) * width + j) == len)
uf.union(i * width + j, len);
else
uf.union((i-1) * width + j, i * width + j);
}
if(board[i][j-1] == 'O'){
if(uf.find(i * width + j-1) == len)
uf.union(i * width + j, len);
else
uf.union(i * width + j-1, i * width + j);
}
}
}
}
}
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
if(board[i][j] == 'O' && uf.find(i*width + j) != len){
board[i][j] = 'X';
}
}
}
}
}