文章目录
定义
并查集是一种树形的数据结构,用来表示一些不相交集合的合并和查询。每棵树的节点指向他的父节点,树的根节点指向他自己;
初始化:
//单独形成集合,每个节点的祖先为自己
int fa[size];
for(int i=0;i<size;i++)
fa[i]=i;
查找:
int findfather(int fa[], int x)
{
if(fa[x]!=x) //如果自己的祖先不是自己,说明不是集合的祖先
fa[x]=findfather(fa,fa[x]); //查找集合的祖先,并进行压缩
return fa[x];
}
合并:
bool unionn(int fa[],int i, int j)
{
int fa_i=findfa(fa,i);
int fa_j=findfa(fa,j);
if(fa_i!=fa_j)
{
fa[fa_i]=fa_j; //若两个节点祖先不同,不在同一个集合;则将其合并,其中一个祖先设为另一个的祖先,
return true; //刚建立集合,返回true
}
return false; //之前就存在集合,返回false
}
几道例题
剑指offer II 116 朋友圈
def findfather(fa,i):
if fa[i]!=i:
fa[i]=findfather(fa,fa[i])
return fa[i]
def union(fa,i,j):
fa_i=findfather(fa,i)
fa_j=findfather(fa,j)
if fa_i!=fa_j:
fa[i]=fa_j
return True
return False
if __name__=='__main__':
n=int(input())
M=[]
for i in range(n):
m=[int(j) for j in input().split(',')]
M.append(m)
fa=[-1]*n
for i in range(n):
fa[i]=i
count=n
for i in range(n):
for j in range(i+1,n):
if M[i][j]==1 and union(fa, i, j):
count-=1
print(count)
剑指offer II 117 相似的字符串
class Solution {
public:
// 通过统计不同字符串的个数,判断是否相似
bool similarity(string s1, string s2)
{
int diff=0;
for(int i=0;i<s1.length();i++)
{
if(s1[i]!=s2[i])
diff++;
}
if(diff<=2)
return true;
else
return false;
}
//查找
int findfateher(int fa[],int i)
{
if(fa[i]!=i)
fa[i]=findfateher(fa,fa[i]);
return fa[i];
}
//合并
bool unionn(int fa[], int i, int j)
{
int fa_i=findfateher(fa,i);
int fa_j=findfateher(fa,j);
if(fa_i!=fa_j)
{
fa[fa_i]=fa_j;
return true;
}
return false;
}
int numSimilarGroups(vector<string>& strs) {
int n=strs.size();
int fa[n];
for(int i=0;i<n;i++)
{
fa[i]=i;
}
//初始化,每个字符串都是独立的,所以存在n个字符组
int nums=n;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
//判断两个字符串是否相似,并且之前是否已经联通,字符组数量减一
if(similarity(strs[i],strs[j])&&unionn(fa,i,j))
{
nums--;
}
}
}
return nums;
}
};
剑指offer II 118 多余的边
class Solution {
public:
// 查找
int findfa(int fa[], int i)
{
if(fa[i]!=i)
fa[i]=findfa(fa,fa[i]);
return fa[i];
}
// 合并
bool unionn(int fa[],int i, int j)
{
int fa_i=findfa(fa,i);
int fa_j=findfa(fa,j);
if(fa_i!=fa_j)
{
fa[fa_i]=fa_j;
return true; //若之前不存在连接,则建立连接,返回true
}
return false; //之前存在连接,返回false
}
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n=edges.size();
int maxleaf=0;
//查找最大节点的值
for(int i=0;i<n;i++)
{
maxleaf=max(maxleaf,edges[i][0]);
maxleaf=max(maxleaf,edges[i][1]);
}
int fa[maxleaf+1]; //此处记的加1,因为从1开始到n;
for(int i=0;i<maxleaf+1;i++)
{
fa[i]=i;
}
int i;
for(auto edge:edges)
{
if(!unionn(fa,edge[0],edge[1])) //判断是否形成环
return edge;
}
return vector<int> {};
}
};