並查集學不懂怎麼辦?看這篇就夠了!

並查集

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;
        }
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章