並查集是一種樹型的資料結構,用於處理一些不相交集合(disjoint sets)的合併及查詢問題。常常在使用中以森林來表示。
並查集也被稱為不相交集資料結構。顧名思義,並查集主要操作是合併與查詢,它是把初始不相交的集合經過多次合併操作後合併為乙個大集合,然後可以通過查詢判斷兩個元素是否已經在同乙個集合中了。
在python中,並查集可以通過list或者dict等資料結構實現
547. 朋友圈
給定乙個 n * n 的矩陣 m,表示班級中學生之間的朋友關係。如果m[i][j] = 1,表示已知第 i 個和 j 個學生互為朋友關係,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。
並查集的主要方法有:查詢/連通/判斷是否連通
這道題的**相對較為簡單:
class solution:
def findcirclenum(self, m: list[list[int]]) -> int:
n = len(m)
p = [[i] for i in range(n)] #先生成並查集的節點
ans = n
for i in range(n):
for j in range(i):
if m[i][j] == 1 and p[i] is not p[j]: #如果i和j是好朋友,但p中沒有顯示則
p[i] += p[j] #在p[i]中加入p[j]
for k in p[j]: #對於p[j]中的每個數字,定義其根節點為p[i]
p[k] = p[i]
ans -= 1 #朋友圈的數量 - 1
print(p) #本題結果為[[1, 0], [1, 0], [2]]
return ans
在這道題目中傳統的方式可以將各個方法都實現出來,如下:
class solution(object):
def findcirclenum(self, m):
""":type m: list[list[int]]
:rtype: int
"""# 宣告表示集合的樹,用陣列表示樹,如 parent[5] == -1 表示
# 5 是某個集合的代表,同時也是樹根
parent = [-1] * len(m)
# 為各個集合的深度排個序
rank = dict()
# 只遍歷左下部分
for i in range(len(m)):
for j in range(i):
if m[i][j] == 1:
# 如果兩人是朋友,就把兩人放入同乙個集合
self.union(i, j, parent, rank)
ans = 0
print(parent)
for i in parent: # 檢視有多少集合,即多少個朋友圈
if i == -1:
ans += 1
return ans
def findroot(self, num, parent):
""":num:某個小朋友
:parent:多個集合樹
一直找到這個小朋友所在集合的代表,即樹根
"""while parent[num] != -1:
num = parent[num]
return num
def union(self, x, y, parent, rank):
"""x,y 表示滿足朋友關係的兩小朋友
"""if x == y: # 表示自己和自己是朋友,這個直接返回
return
x = self.findroot(x, parent) # 找到所在集合的代表,可能就是自己
print("x is",x)
y = self.findroot(y, parent)
print("y is",y)
rank_x = rank[x] if x in rank else 0 # 查詢該集合目前的深度
rank_y = rank[y] if y in rank else 0
if x == y: # 檢測到 x, y 已經是在同乙個集合了,直接返回
return
if rank_x > rank_y: # 這裡是做路徑壓縮的,避免樹太深使得 findroot 函式耗時過多
parent[y] = x
elif rank_x < rank_y:
parent[x] = y
else:
parent[x] = y
rank[y] = 1
並查集演算法
所謂並查集,它是乙個集合,這個集合的元素也是集合,他支援三種操作 makeset x 建立乙個只有乙個元素x的集合x0,將這個集合放入並查集中 findset x 在並查集中尋找乙個元素s 注意並查集的元素s也是集合 滿足 x屬於s union x,y 將並查集中的元素s1,s2合併,其中x屬於s1...
並查集演算法
並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。讓每個元素構成乙個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。1 makeset s 建立乙個新的並查集,包含s個單元素集合。2 union x,y 把x ...
並查集演算法
includeint pre 10 int find int x 查詢祖先節點 int i x,j while i r 壓縮路徑 return r void join int x,int y int main 2 食物鏈問題 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈...