文章目录
- 定义
- 几道例题
- [剑指offer II 116 朋友圈](https://www.nowcoder.com/questionTerminal/a5c097f75db8418395b6a0e32c608c38)
- [腾讯2021年校招 朋友圈](https://www.nowcoder.com/questionTerminal/11ee0516a988421abf40b315a2b28d08)
- [剑指offer II 117 相似的字符串](https://leetcode-cn.com/problems/H6lPxb/)
- [剑指offer II 118 多余的边](https://leetcode-cn.com/problems/7LpjUW)
- [剑指offer II 119 最长连续序列](https://leetcode-cn.com/problems/WhsWhI/)
定义
并查集是一种树形的数据结构,用来表示一些不相交集合的合并和查询。每棵树的节点指向他的父节点,树的根节点指向他自己;
初始化:
//单独形成集合,每个节点的祖先为自己
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)
腾讯2021年校招 朋友圈
#include<iostream>
using namespace std;
int findfa(int fa[],int x)
{
if(fa[x]!=x)
fa[x]=findfa(fa,fa[x]);
return fa[x];
}
void unionn(int fa[],int x, int y)
{
int fa_x=findfa(fa,x);
int fa_y=findfa(fa,y);
if(fa_x!=fa_y)
fa[fa_x]=fa_y;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int fa[100001];
int n;
cin>>n;
for(int i=0;i<100001;i++)
fa[i]=i;
while(n--)
{
int x,y;
cin>>x>>y;
unionn(fa,x,y);
}
vector<int> nums(100001);
int max_len=0;
for(int i=0;i<100001;i++)
{
int k=findfa(fa,i);
nums[k]++;
max_len=max(max_len,nums[k]);
}
cout<<max_len<<endl;
}
return 0;
}
剑指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> {};
}
};
剑指offer II 119 最长连续序列
class Solution {
public:
int findfa(unordered_map<int,int>& fa, int i)
{
if(fa[i]!=i)
fa[i]=findfa(fa,fa[i]);
return fa[i];
}
void unionn(unordered_map<int,int>& fa, unordered_map<int,int>& count,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;
count[fa_j]=count[fa_j]+count[fa_i];
}
}
int longestConsecutive(vector<int>& nums) {
unordered_map<int,int> fa;
unordered_map<int,int> count;
set<int> all;
for(int i=0;i<nums.size();i++)
{
fa[nums[i]]=nums[i];
count[nums[i]]=1;
all.insert(nums[i]);
}
for(int i=0;i<nums.size();i++)
{
if(all.count(nums[i]-1)==1)
{
unionn(fa,count,nums[i],nums[i]-1);
}
if(all.count(nums[i]+1)==1)
{
unionn(fa,count,nums[i],nums[i]+1);
}
}
int len=0;
for(int i=0;i<nums.size();i++)
{
len=max(len,count[nums[i]]);
}
return len;
}
};