關於並查集的題目很多,官方給的數據是 30 道(截止 2020-02-20),可是有一些題目雖然官方沒有貼並查集
標籤,可是使用並查集來講確很是簡單。這類題目若是掌握模板,那麼刷這種題會很是快,而且犯錯的機率會大大下降,這就是模板的好處。python
我這裏總結了幾道並查集的題目:算法
你們能夠學了模板以後去套用一下上面的三道題,作不出來的能夠看看個人題解。segmentfault
並查集算法,主要是解決圖論中「動態連通性」問題的性能
Union-Find 算法解決的是圖的動態連通性問題,這個算法自己不難,能不能應用出來主要是看你抽象問題的能力,是否可以把原始問題抽象成一個有關圖論的問題。spa
若是你對這個算法不是很明白,推薦看一下這篇文章Union-Find 算法詳解,講的很是詳細。code
你能夠把並查集的元素當作部門的人,幾我的能夠組成一個部門個數。blog
並查集核心的三個方法分別是union
, find
, connected
。ci
union
: 將兩我的所在的兩個部門合併成一個部門(若是兩我的是相同部門,實際山不須要合併)
(圖來自 labuladong)leetcode
find
: 查找某我的的部門 leaderconnnected
: 判斷兩我的是不是一個部門的
(圖來自 labuladong)get
這是一個我常常使用的模板,我會根據具體題目作細小的變化,可是大致是不變的。
class UF: parent = {} cnt = 0 def __init__(self, M): # 初始化 parent 和 cnt def find(self, x): while x != self.parent[x]: x = self.parent[x] return x def union(self, p, q): if self.connected(p, q): return self.parent[self.find(p)] = self.find(q) self.cnt -= 1 def connected(self, p, q): return self.find(p) == self.find(q)
若是你想要更好的性能,這個模板更適合你,相應地代碼稍微有一點複雜。
class UF: parent = {} size = {} cnt = 0 def __init__(self, M): # 初始化 parent,size 和 cnt def find(self, x): while x != self.parent[x]: x = self.parent[x] # 路徑壓縮 self.parent[x] = self.parent[self.parent[x]]; return x def union(self, p, q): if self.connected(p, q): return # 小的樹掛到大的樹上, 使樹儘可能平衡 leader_p = self.find(p) leader_q = self.find(q) if self.size[leader_p] < self.size[leader_q]: self.parent[leader_p] = leader_q else: self.parent[leader_q] = leader_p self.cnt -= 1 def connected(self, p, q): return self.find(p) == self.find(q)
你們能夠根據狀況使用不一樣的模板。