0
点赞
收藏
分享

微信扫一扫

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

f12b11374cba 2022-04-20 阅读 31

文章目录

定义

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

初始化:

//单独形成集合,每个节点的祖先为自己
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> {};
    }
};
举报

相关推荐

0 条评论