数据结构:并查集的初始化、查找及合并操作,剑指offer几道例题:朋友圈、相似字符串、多余的边及最长连续序列

定义

并查集是一种树形的数据结构,用来表示一些不相交集合的合并和查询。每棵树的节点指向他的父节点,树的根节点指向他自己;

初始化:

//单独形成集合,每个节点的祖先为自己
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;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值