并查集
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。常用在判断无项图中连通性问题。
主要操作
1.初始化
把每个点所在集合初始化为-1。
通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。
vector<int> v;
UnionFindSet(int n)
{
v.resize(n,-1);
}
2.查找
查找元素所在的集合,即根节点。
int FindRoot(int x)
{
int index=x;
while(v[index]>=0)
{
//说明不是根,继续查找它的内容是否是根
index=v[index];
}
return index;
}
3.合并
将两个元素所在的集合合并为一个集合。
通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的“查找”操作实现。
void Union(int x1,int x2)
{
int root1=FindRoot(x1);
int root2=FindRoot(x2);
if(root1==root2)return;//已经联通
else
{
//让一个根去当作另一个根的根
v[root1]+=v[root2];
v[root2]=root1;
}
}
最终数据结构代码:
class UnionFindSet{
public:
UnionFindSet(int n)
{
v.resize(n,-1);
}
int FindRoot(int x)
{
int index=x;
while(v[index]>=0)
{
//说明不是根,继续查找它的内容是否是根
index=v[index];
}
return index;
}
void Union(int x1,int x2)
{
int root1=FindRoot(x1);
int root2=FindRoot(x2);
if(root1==root2)return;//已经联通
else
{
//让一个根去当作另一个根的根
v[root1]+=v[root2];
v[root2]=root1; //root2的根为下标是root1的点
}
}
//获得分组个数
int GetCount()
{
int sum=0;
for(int i=0;i<v.size();++i)
{
if(v[i]<0)sum++;
}
return sum;
}
private:
vector<int> v;
};
PS:Leetcode 547.朋友圈问题
class Solution {
public:
int findCircleNum(vector<vector<int>>& r) {
int n=r.size();
UnionFindSet ufs(n);
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
if(r[i][j]){
ufs.Union(i,j);
}
}
}
return ufs.GetCount();
}
};