在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /、\ 或空格构成。这些字符会将方块划分为一些共边的区域。
(请注意,反斜杠字符是转义的,因此 \ 用 "\\" 表示。)。
返回区域的数目。
示例 1:
输入:
[
" /",
"/ "
]
输出:2
解释:2x2 网格如下:
示例 2:
输入:
[
" /",
" "
]
输出:1
解释:2x2 网格如下:
示例 3:
输入:
[
"\\/",
"/\\"
]
输出:4
解释:(回想一下,因为 \ 字符是转义的,所以 "\\/" 表示 \/,而 "/\\" 表示 /\。)
2x2 网格如下:
示例 4:
输入:
[
"/\\",
"\\/"
]
输出:5
解释:(回想一下,因为 \ 字符是转义的,所以 "/\\" 表示 /\,而 "\\/" 表示 \/。)
2x2 网格如下:
示例 5:
输入:
[
"//",
"/ "
]
输出:3
解释:2x2 网格如下:
提示:
1 <= grid.length == grid[0].length <= 30
grid[i][j] 是 '/'、'\'、或 ' '。
思路:我们考虑将网格中的每一格看做由左划线或者右划线分成的两格,而垂直方向仍然正常,此时我们得到了一个m*(2n)的网格图,这样我们可以通过左划线或者右划线判断哪些网格时连通的,而对于连通合并的操作我们采用并查集。
注意:对于竖直方向连通情况较复杂,代码中由不懂的地方可以留言。
class Solution {
private int[] f;
public int regionsBySlashes(String[] grid) {
int ans=0;
int m=grid.length;
int n=grid[0].length()*2;
int size=m*n;
f=new int[size];
boolean[] flag=new boolean[size];
for(int i=0;i<size;i++)
f[i]=i;
for(int i=0;i<m;i++)
for(int j=0;j<n;j+=2) {
if(grid[i].charAt(j/2)==' ')
merge(i*n+j,i*n+j+1);
if(j>0)
merge(i*n+j-1,i*n+j);
}
for(int j=0;j<n;j+=2)
for(int i=0;i<m-1;i++) {
if((grid[i+1].charAt(j/2)=='\\' || grid[i+1].charAt(j/2)==' ')
&& (grid[i].charAt(j/2)=='/' || grid[i].charAt(j/2)==' '))
merge(i*n+j+1,(i+1)*n+j+1);
else if((grid[i+1].charAt(j/2)=='\\' || grid[i+1].charAt(j/2)==' ')
&& (grid[i].charAt(j/2)=='\\' || grid[i].charAt(j/2)==' '))
merge(i*n+j,(i+1)*n+j+1);
else if((grid[i+1].charAt(j/2)=='/' || grid[i+1].charAt(j/2)==' ')
&& (grid[i].charAt(j/2)=='\\' || grid[i].charAt(j/2)==' '))
merge(i*n+j,(i+1)*n+j);
else if((grid[i+1].charAt(j/2)=='/' || grid[i+1].charAt(j/2)==' ')
&& (grid[i].charAt(j/2)=='/' || grid[i].charAt(j/2)==' '))
merge(i*n+j+1,(i+1)*n+j);
}
for(int i=0;i<m;i++)
for(int j=0;j<n;j++) {
int index=find(i*n+j);
if(flag[index])
continue;
ans++;
flag[index]=true;
}
return ans;
}
private void merge(int x,int y) {
int t1=find(x);
int t2=find(y);
if(t1!=t2)
f[t1]=t2;
}
private int find(int x) {
if(f[x]==x)
return x;
return f[x]=find(f[x]);
}
}