959. 由斜杠划分区域
思路:
其实区域就可以看作是一个环,将n * n的网络看作有(n+1) * (n+1)个点,先用内部的点来构建并查集,然后再封闭边界,在合并的时候判断当前这条边是否会造成一个环的生成(也就是判断要合并的两个顶点的root是否相同),如果会则环的数量++,最后返回环的数量即可。
class Solution {
public int regionsBySlashes(String[] grid) {
//图,并查集
int n=grid.length; // n*n的网格,(n+1)*(n+1)个点
int ans=0;
int[] parent=new int[(n+1)*(n+1)];
for(int i=0;i<(n+1)*(n+1);i++){
parent[i]=i;
}
// 处理内部
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(grid[i].charAt(j)=='/'){
int from=(i*(n+1))+j+1;// from的顶点编号
int to=((i+1)*(n+1))+j;
if(!union(parent,from,to)){
ans++;
}
}
else if(grid[i].charAt(j)=='\\'){
int from=(i*(n+1))+j;// from的顶点编号
int to=((i+1)*(n+1))+j+1;
if(!union(parent,from,to)){
ans++;
}
}
}
}
// 边界最后再合并
// 先封闭上下边
for(int i=0;i<2;i++){
for(int j=0;j<n;j++){
int from=(i*(n+1)*n)+j;
int to=from+1;
if(!union(parent,from,to)){
ans++;
}
}
}
//封闭左右边
for(int i=0;i<2;i++){
for(int j=0;j<(n+1)*n;j+=n+1){
int from=(i*n)+j;
int to=from+n+1;
if(!union(parent,from,to)){
ans++;
}
}
}
return ans;
}
int find(int[] parent,int a){
if(parent[a]!=a){
parent[a]=find(parent,parent[a]);
}
return parent[a];
}
boolean union(int[] parent,int a,int b){
int roota=find(parent,a);
int rootb=find(parent,b);
if(roota!=rootb){
parent[roota]=rootb;
return true;
}
return false;
}
}