leetcode 959. Area divided by slashes
Question stem
In an N x N grid consisting of 1 x 1 squares, each 1 x 1 square is composed of /, \ or spaces. These characters divide the square into co-sided areas.
(Please note that the backslash character is escaped, so \ is represented by "\".).
Returns the number of regions.
Example 1:
Input:
[
"/",
"/"
]
Output: 2
Example 2:
Input:
[
"/",
" "
]
Output: 1
Example 3:
Input:
[
"\/",
"/\"
]
Output: 4
Explanation: (Recall that because the \ character is escaped, "\/" means /, and "/\" means /\. )
Example 4:
Input:
[
"/\",
"\/"
]
Output: 5
Explanation: (Recall that because the \ character is escaped, "/\" means /\, and "\/" means /. )
Example 5:
Input:
[
"//",
"/ "
]
Output: 3
Hint:
1 <= grid.length == grid[0].length <= 30
grid[i][j] is'/','', or ''.
answer
Using the idea of union search, divide each 1x1 square into a left triangle and a right triangle, and set the connected triangles to the same ancestor. The essence is to find the number of connected branches.
class Solution {
public:
//寻找最大祖先,并返回最大祖先在ancestor数组中的下标,没有祖先返回-1
int findAncestor(int n,vector<int>& ancestor){
while(ancestor[n] != n){
n = ancestor[n];
}
return n;
}
//获得给定坐标方块的对应三角块在祖先数组中的下标
int getLeftTriangle(vector<string>& grid,int x,int y,int n){
return 2 * x * n + y * 2;
}
int getRightTriangle(vector<string>& grid,int x,int y,int n){
return 2 * x * n + y * 2 + 1;
}
int getUpperTriangle(vector<string>& grid,int x,int y,int n){
if(grid[x][y] == '/'){
//斜杠方块的上三角是左三角
return 2 * x * n + y * 2;
}else{
return 2 * x * n + y * 2 + 1;
}
}
int getLowerTriangle(vector<string>& grid,int x,int y,int n){
if(grid[x][y] == '/'){
//斜杠方块的下三角是右三角
return 2 * x * n + y * 2 + 1;
}else{
return 2 * x * n + y * 2;
}
}
int regionsBySlashes(vector<string>& grid) {
int n = grid.size();
int components = 0;
//给每个1x1块的左右小三角一个祖先的空间
vector<int> ancestor(2000,-1);
for(int i = 0 ; i < n ; ++i){
for(int j = 0 ; j < n ; ++j){
int currentLeftTri = getLeftTriangle(grid,i,j,n);
int currentRightTri = getRightTriangle(grid,i,j,n);
int preLeftTri = getLeftTriangle(grid,i,j-1,n);
int preRightTri = getRightTriangle(grid,i,j-1,n);
//现将当前方块的左右三角的祖先都设为自己
ancestor[currentLeftTri] = currentLeftTri;
components++;
ancestor[currentRightTri] = currentRightTri;
components++;
if(grid[i][j] == ' '){
//当前方块没有斜杠,左右连通
if(findAncestor(currentLeftTri,ancestor) != findAncestor(currentRightTri,ancestor) ){
//当前方块右三角和左三角的祖先不同,将当前方块右三角的最大祖先的祖先设为左三角的最大祖先
ancestor[findAncestor(currentRightTri,ancestor)] = findAncestor(currentLeftTri,ancestor);
components--;
}
}
if(j != 0){
//此时不是第一列,左三角和左侧方块右三角连通
if(findAncestor(preRightTri,ancestor) != findAncestor(currentLeftTri,ancestor) ){
//左侧方块右三角和当前方块左三角祖先不同,将当前方块左三角的最大祖先的祖先设为左侧方块右三角的最大祖先
ancestor[findAncestor(currentLeftTri,ancestor)] = findAncestor(preRightTri,ancestor);
components--;
}
}
if(i != 0){
//此时不是第一行,上三角和上册方块下三角连通
int upperLowerTri = getLowerTriangle(grid,i-1,j,n);
int currentUpperTri = getUpperTriangle(grid,i,j,n);
if(findAncestor(upperLowerTri,ancestor) != findAncestor(currentUpperTri,ancestor) ){
//上侧方块下三角和当前方块祖先不同,将当前方块上三角的最大祖先的祖先设为上侧方块下三角的最大祖先
ancestor[findAncestor(currentUpperTri,ancestor)] = findAncestor(upperLowerTri,ancestor);
components--;
}
}
}
}
return components;
}
};