并查集学不懂怎么办?看这篇就够了!

并查集

BALL BALL各位老哥点赞关注收藏,爱死你们了。

什么是并查集?

答:一种数据结构,专门用于组织管理一群离散数据的方法。
并查集顾名思义,有两个功能。一、查找一个数据所处在的数据集合的分类标签。 二、将两个原本无交集的数据集合
并在一起。
这东西有什么用? 答:通过对数据所在空间范围的合并,可以快速的对数据性质做出判断。如判断一个点是否与另一
个点具有相同的属性。如果不使用并查集结构,每一次搜索只能使用bfs或dfs。 如使用并查集可通过对一个节点到该
集合标签的路径值进行判断。代码简洁,且可以通过路径压缩,将查找时间复杂度优化为O(1)

什么是路径查找压缩?

在我们使用一个数据的时候,只需要查找他属于的集合标签,如{a,b,c} 。并不需要知道,这个数据到达其标签的
路径。
在新添加一个数据到一个集合的时候,我们只知道与其相关联的数据。如果这个数据在与新添加数据链接之前便已
指向集合标签,那么只需要O(1)的查找复杂度。
	
									例\
	step One			step Two 			step Three
	1							1							1
	2						2		3					2	3	4
	3
	4
	连接1与2			3与2连接,但可以直接			4与3连接,但3直接指向1,直接将4归入1的集合
					查询到2指向1,直接连接到1

若不使用路径压缩,则每次添加一个数据到任意一个集合的话,时间复杂度为O(n)

实现思路讲解

1、初始化一个数组int [] father,代表每一个数据所处于的集合,因为一开始,每个数据都是孤立的,所以把
father[i]=i。
2、通过find 函数(既在新添加一个数据连接关系或图的边的时候)找到集合标签。并将其相连(如果两个点已处于一
个集合),则不进行操作
3、添加完毕后,根据father[i]的性质进行一定的操作,这部分函数一般都写在main方法里面

代码

class Solution {
    static int [] father;
    public int findCircleNum(int[][] M) {
        father =new int[M.length];
        for(int i=0;i<father.length;i++)father[i]=i;
        for(int i =0;i<M.length;i++){
            for(int j =0;j<M.length;j++){
                if(M[i][j]==1)merge(i,j);
            }
        }
        HashSet<Integer> set=new HashSet<Integer>();
        for(int i =0;i<father.length;i++){
            set.add(find(father[i]));
        }
        return set.size();
    }
    public static int find(int a ){
        return (father[a]==a ? a : (father[a]=find(father[a])));
    }
    public static void merge(int a ,int b ){
        int fa=find(a);int fb=find(b);
        if(fa!=fb){
            father[fa]=fb;
        }
        
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42499133/article/details/105925162
今日推荐