在由 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 x 1 方格组成的 N x N 网格,N为grid的长度。且grid里的每一个字符串的长度也是N,第i个字符串表示对第i行的处理。因此在处理字符串的时候不需要过多考虑index越界问题
二
下面直接放代码,分析写在代码的注释
class Solution {
public int regionsBySlashes(String[] grid) {
//将每一个格子分成四个小格子,讨论当字符分别为“/”“\\”" "是的合并情况,划分的细节如下
/**
0 0
1 2 1 2
3 3
0 0
1 2 1 2
3 3
2*2的正方形划分情况如上图
**/
//不是最后一行的时候,向下合并,无论下一行的方格怎样划分,当前格子的3总是和下一行的0 需要合并
//不是第一行的时候,向上合并,无论上一行的方格怎样划分,当前格子的0总是和上一行的3需要合并
//列的情况类似于 行
int n = grid.length;
DisJointU dsj = new DisJointU(4*n*n);
for (int r = 0;r<n;++r){
for (int c=0;c<n;++c){
int start = 4*(r*n+c);//每个方格的起始index
char cur = grid[r].charAt(c);
// 字符为\\或者空格的时候 合并策略
//字符为空格 方格的四个小块都要合并在一起;
if (cur!='/'){
dsj.union(start+0,start+2);
dsj.union(start+1,start+3);
}
// 字符为/或者空格的时候 合并策略
if (cur!='\\'){
dsj.union(start+0,start+1);
dsj.union(start+2,start+3);
}
// 不是第一行时的合并策略
if (r>0){
dsj.union(start+0,start-4*n+3);
}
// 不是最后一行时的合并策略
if (r<n-1){
dsj.union(start+3,start+4*n+0);
}
// 不是第一列时的合并策略
if (c>0){
dsj.union(start+1,start-4+2);
}
// 不是最后一列时的合并策略
if (c<n-1){
dsj.union(start+2,start+4+1);
}
}
}
// HashSet<Integer> hs = new HashSet<>();
// for (int i=0;i<4*n*n;++i){
// hs.add(dsj.find(i));
// }
// return hs.size();
int res =0;
for (int i=0;i<4*n*n;++i){
if(i==dsj.find(i)){
res++;
}
}
return res;
}
}
class DisJointU{
public DisJointU() {
}
int[] pre;
public DisJointU(int n) {
pre = new int[n];
for (int i=0;i<n;++i){
pre[i] = i;
}
}
public int find(int x){
if(pre[x]==x)return x;
int root = find(pre[x]);
return pre[x]=root;
}
public void union(int a, int b){
int x = this.find(a);
int y = this.find(b);
pre[x] = y;
}
}