在由 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] 是 '/'、'\'、或 ' '。
解答
并查集,将每个方格按照两个对角线划分为上下左右(依次编号为0,1,2,3)四个三角形,如果对应字符为' '
则将这四个三角形都合并,如果字符为'/'
,则分别将三角形0, 3
,1, 2
进行合并,如果字符为'\\'
,则分别将三角形0, 1
,2, 3
进行合并。此外,上下和左右相邻的方格也应该进行合并。最后并查集中独立连通分量的个数就是所求的区域数量。
class DSU{
public:
vector<int> parent;
vector<int> rank;
int n;
DSU(int n) : n(n){
rank.resize(n, 1);
parent.resize(n);
for(int i = 0; i < n; i++){
parent[i] = i;
}
}
int find(int i){
if(i != parent[i]){
int temp = find(parent[i]);
parent[i] = temp;
}
return parent[i];
}
void merge(int i, int j){
int pi = find(i);
int pj = find(j);
if(pi != pj){
if(rank[pi] > rank[pj]){
swap(pi, pj);
}
parent[pi] = pj;
rank[pj] += rank[pi];
}
return;
}
};
class Solution {
public:
int regionsBySlashes(vector<string>& grid) {
int n = grid.size();
// 总共有 4*n*n个三角形
DSU dsu(4 * n * n);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
// 将每个方格中的四个三角形合并
int index = 4 * (i * n + j);
if(grid[i][j] == ' '){
dsu.merge(index, index + 1);
dsu.merge(index, index + 2);
dsu.merge(index, index + 3);
}
else if(grid[i][j] == '/'){
dsu.merge(index, index + 3);
dsu.merge(index + 1, index + 2);
}
else if(grid[i][j] == '\\'){
dsu.merge(index, index + 1);
dsu.merge(index + 2, index + 3);
}
// 将相邻的方格合并
if(j > 0){
dsu.merge(index + 3, index - 3);
}
if(i > 0){
dsu.merge(index, index - 4 * n + 2);
}
}
}
int result = 0;
for(int i = 0; i < 4 * n * n; i++){
if(dsu.find(i) == i)
result++;
}
return result;
}
};