2021-1-25表單元素美化
阿新 • • 發佈:2021-01-26
在由 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;
}
};