Union Find算法基礎css
Union Find算法用於處理集合的合併和查詢問題,其定義了兩個用於並查集的操做:git
並查集是一種樹形的數據結構,其可用數組或unordered_map表示:github
Find操做即查找元素的root,當兩元素root相同時斷定他們屬於同一個子集;Union操做即經過修改元素的root(或修改parent)合併子集,下面兩個圖展現了id[6]由6修改成9的變化:算法
圖片來源 這裏數組
Union Find算法應用數據結構
Union Find可用於解決集合相關問題,如判斷某元素是否屬於集合、兩個元素是否屬同一集合、求解集合個數等,算法框架以下:框架
//261. Graph Valid Tree bool validTree(int n, vector<pair<int, int>>& edges) { vector<int> num(n,-1); for(auto edge:edges){ //find查看兩點是否已在同一集合 int x=find(num,edge.first); int y=find(num,edge.second); if(x==y) return false; //兩點已在同一集合狀況下則出現環 //union讓兩點加入同一集合 num[x]=y; } return n-1==edges.size(); } int find(vector<int>&num,int i){ if(num[i]==-1) return i; return find(num,num[i]); //id[id[...id[i]...]] }
一些狀況下爲清晰和解偶會將Uinon Find實現爲一個類,獨立出明顯的Union和Find兩個操做。優化
相關LeetCode題:spa
947. Most Stones Removed with Same Row or Column 題解
算法優化
有兩種經常使用的方法用來下降並查集樹形結構的高度、以減小Uinon Find算法的時間複雜度,這兩種方法是:
Weighting(或稱做Ranking): 使用多一個數組記錄每一個集合的size,Uinon時將size小的集合掛到size大的集合下,例如:
對三、5 Uinon,因3所在集合元素size 4大於5所在集合元素size 2,將6掛到9下而不是將9掛到6下。
Path compression: 對一個集合下的元素直接掛到root之下,而不是掛到其parent,path compression實現很簡單隻需在Find中加一行代碼:
string find(unordered_map<string,string>& root,string s){ if(root[s]!=s) root[s]=find(root,root[s]); return root[s]; }
加入path compression也能實現減小並查集樹高度的效果,圖示以下:
Weighting和Path compression兩種方法能夠同時使用,這樣使得對N個元素進行M次Union Find操做的時間複雜度能夠減小到 (M+N)lgN。因lgN隨N的增加變化很小,因此總體算法時間複雜度接近於線性的時間複雜度。
相關LeetCode題: