随手笔记:
这篇文章讲解leetcode题库中:959.由斜杠划分区域。
题目介绍:(点击此处可以转到leetcode原题)
题目描述非常简单,用通俗的语言就是,现在有正方形中可以填充“ ”、“\”、“/”,将正方形分成如下图所示的区域。现在有N*N的大正方形中由下面3种小正方形组成。
例如下边左边的图是一个示例,是2*2的大正方形 ,有3个区域。可以将其分解为右侧图案,小正方形1,2,3均为上图第三个小正方形,第四个为上图第一个小正方形。
题目用到的知识:并查集,并查集是非常好用的一种求联连通分量的算法。不会的可以看一下这篇文章,我个人感觉还是不错的。(点此处跳转)
并查集可以理解:查找某一个结点的祖先,将不同祖先的节点合并就可以了。
本题是将3种小正方形分为4个小正方形,并且按下图所示顺序标号吗,以上图3个区域的大正方形为例。
单元内合并(按上图顺序来解释):
0,1,2,3可以合并为一个,即union(0,1)、(1,2)、(2,3);原来是4个连通分量,现在经过3次合并,数量减3,所以变成一个。
0,3;1,2可以合并为两个,即union(0,3)、(1,2);原来是4个连通分量,现在经过2次合并,数量减2,所以变成两个。
0,1;2,3可以合并为两个,即union(0,1)、(2,3);原来是4个连通分量,现在经过2次合并,数量减2,所以变成两个。
单元间合并,(可以多画几次图)可以得出两个结论:
-
一个格子中最下方的三角形,必然和下面的格子(如果存在)中最上方的三角形连通;
-
一个格子中最右方的三角形,必然和右边的格子(如果存在)中最左方的三角形连通。
-
举例:对于下方第一个正方形,其必然与蓝色,橘色相连通,即第一个的序号1与右侧的序号3;第一个的序号2与下方的序号0。
leetcode可通过代码(C++):
class UnionFind{
private:
int count; //计数联通分量数目
int *parent; //保存每个节点的祖先
public:
UnionFind(int size) //首先根据数量初始化,并且每个节点的祖先是自己
{
count=size;
parent=new int[size];
for(int i=0;i<size;i++)
{ parent[i]=i; }
}
int find(int x) //找出该节点的祖先,一直找到最上方。(重点,可以树状图辅助理解)
{
while(x!=parent[x])
{
parent[x]=parent[parent[x]];
x=parent[x];
}
return x;
}
void union_xy(int x,int y) //将两个几点合并
{
int root_x=find(x);
int root_y=find(y);
if(root_x==root_y)
{
return;
}
//直接找到两个结点的祖先,然后将某一个祖先的祖先由它本身修改为另一个;
//这里是x的祖先是root_x;那么原来root_x的祖先是他本身,现在修改为另一个y的祖先root_y;
//当修改一次,这两个就属于同一个祖先了,连通分量数目就可以减一;
parent[root_x]=root_y;
count--;
}
int num()
{
return count;
}
~UnionFind()
{
delete []parent;
}
};
class Solution {
public:
int regionsBySlashes(vector<string>& grid) {
//先将string字符转换为char数组。
int N=grid.size();
vector<char> grid_2;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
grid_2.push_back(grid[i][j]);
}
}
int size=4*N*N;
int char_num=N*N;
UnionFind test=UnionFind(size);
//进行单元内的合并。
for(int i=0;i<char_num;i++)
{
if(grid_2[i]==' ')
{
test.union_xy(4*i,4*i+1);
test.union_xy(4*i+1,4*i+2);
test.union_xy(4*i+2,4*i+3);
}
else if(grid_2[i]=='/')
{
test.union_xy(4*i,4*i+3);
test.union_xy(4*i+1,4*i+2);
}
else if(grid_2[i]=='\\')
{
test.union_xy(4*i,4*i+1);
test.union_xy(4*i+2,4*i+3);
}
}
//单元间合并。
for(int i=0;i<char_num;i++)
{
int j=i%N;
int k=i/N;
if(j!=N-1) test.union_xy(4*i+1,4*(i+1)+3);
if(k!=N-1) test.union_xy(4*i+2,4*(i+N));
}
return test.num();
}
};
有不明白的地方可以私信给我,可以进行进一步讲解。