版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sengo_GWU/article/details/83021550
parents = range(n)
rank = [0] * n
def find(edge):
if parents[edge] != edge:
parents[edge] = find(parents[edge])
return parents[edge]
def union(x, y):
x, y = find(x), find(y)
if x != y:
if rank[x] >= rank[y]:
parents[y] = x
rank[x] += rank[x] == rank[y]
else:
parents[x] = y
=======================================
Traveling is Fun
https://leetcode.com/discuss/interview-question/202553/Traveling-is-Fun/?goto=old
def connectedCities(n, g, originCities, destinationCities):
n += 1
parent = list(range(n))
rank = [0] * n
def find(x):
if x != parent[x]:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
x, y = find(x), find(y)
if x != y:
if rank[x] >= rank[y]:
parent[y] = x
rank[x] += rank[x] == rank[y]
else:
parent[x] = y
for i in range(g + 1, n):
f = 2
while i * f < n:
union(i, i * f)
f += 1
return [int(find(s) == find(d)) for s, d in zip(originCities, destinationCities)]
947. Most Stones Removed with Same Row or Column
https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/solution/
Time Complexity: O(N \log N)O(NlogN), where NN is the length of stones
. (If we used union-by-rank, this can be O(N * \alpha(N))O(N∗α(N)), where \alphaα is the Inverse-Ackermann function.)
class DSU:
def __init__(self, N):
self.p = range(N)
def find(self, x):
if self.p[x] != x:
self.p[x] = self.find(self.p[x])
return self.p[x]
def union(self, x, y):
xr = self.find(x)
yr = self.find(y)
self.p[xr] = yr
class Solution(object):
def removeStones(self, stones):
N = len(stones)
dsu = DSU(20000)
for x, y in stones:
dsu.union(x, y + 10000)
return N - len({dsu.find(x) for x, y in stones})
305. Number of Islands II
不用Union by rank 也能通过
class Solution(object):
def numIslands2(self, m, n, positions):
"""
:type m: int
:type n: int
:type positions: List[List[int]]
:rtype: List[int]
"""
parent, rank = {}, {}
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # path compression
return parent[x]
def union(x, y):
p1, p2 = find(x), find(y)
if p1 == p2:
return 0
else: # union by rank
if rank[p1] < rank[p2]:
parent[p1] = p2
else:
parent[p2] = p1
if rank[p1] == rank[p2]:
rank[p1] += 1
return 1
res, count = [], 0
for i, j in positions:
x = i, j
parent[x] = x
rank[x] = 0
count += 1
for y in (i+1, j), (i-1, j), (i, j+1), (i, j-1):
if y in parent:
count -= union(x, y)
res.append(count)
return res
323. Number of Connected Components in an Undirected Graph
class Solution(object):
def countComponents(self, n, edges):
parents = range(n)
def find(a):
if parents[a] != a:
return find(parents[a])
return a
def union(b, p1):
while True:
p = parents[b]
parents[b] = p1
if p != b:
b = p
else:
break
for a, b in edges:
p1, p2 = find(a), find(b)
if p1 != p2:
union(b, p1)
return len({find(x) for x in xrange(n)})
721. Accounts Merge
class Solution(object):
def init(self, accounts):
self.parents = {}
self.owner = {}
for acc in accounts:
owner = acc[0]
root = acc[1] # 第一个邮箱为root, root的特点是指向自己
self.owner[root] = owner
for email in acc[1:]:
if email not in self.parents:
self.parents[email] = root
else:
self.union(root, self.parents[email])
def find(self, x):
if self.parents[x] == x:
return x
self.parents[x] = self.find(self.parents[x])
return self.parents[x]
def union(self, x, y):
px = self.find(x)
py = self.find(y)
self.parents[py] = px
def accountsMerge(self, accounts):
"""
:type accounts: List[List[str]]
:rtype: List[List[str]]
"""
self.init(accounts)
for acc in accounts:
for email in acc[1:]:
self.find(email) # 每次find都会把所有上面的节点指向root
groups = list(set(self.parents.values())) # values的值是父节点
res = []
for j in xrange(len(groups)):
temp = []
for key in self.parents:
if self.parents[key] == groups[j]:
temp.append(key)
temp = sorted(temp)
temp.insert(0, self.owner[groups[j]])
res.append(temp)
return res
下面的TLE??
class Solution(object):
def accountsMerge(self, accounts):
parent = {}
owner = {}
def find(email):
if parent[email] != email:
parent[email] = find(parent[email])
return parent[email]
def union(e1, e2):
p1 = parent[e1]
p2 = parent[e2]
parent[p2] = p1
for acc in accounts:
name = acc[0]
root = acc[1]
owner[root] = name
for e in acc[1:]:
if e not in parent:
parent[e] = root
else:
union(root, parent[e])
for e in parent:
find(e)
roots = list(set(parent.values()))
re = []
for root in roots:
temp = []
for e in parent:
if parent[e] == root:
temp.append(e)
temp.sort()
temp.insert(0, owner[root])
re.append(temp)
return re
261. Graph Valid Tree
class Solution(object):
def validTree(self, n, edges):
"""
:type n: int
:type edges: List[List[int]]
:rtype: bool
"""
parents = range(n)
def find(b): # 找到root parent
if parents[b] != b:
return find(parents[b])
return b
def union(b, p1): # 把b和b的所有parent 的parent设为p1
while True:
p = parents[b]
parents[b] = p1
if p != b:
b = p
else:
break
for a, b in edges: # 如果edge a, b have the same root parent, then circle, else union
p1 = find(a)
p2 = find(b)
if p1 == p2:
return False # circle
else:
union(b, p1) # union
for i in xrange(n): # check if all the node have the same root parent, if not,there exist more than 1 tree
if i == 0:
p = find(i)
else:
print i, find(i)
if find(i) != p:
return False
return True