-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathsolution2.py
51 lines (40 loc) · 1.81 KB
/
solution2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from collections import defaultdict
from typing import List
class DisjointSet:
def __init__(self, length: int):
self.rank = [1] * length
self.parent = [i for i in range(length)]
def union(self, u: int, v: int) -> None:
# Find their root nodes of two respective nodes
u_root, v_root = self.find(u), self.find(v)
if u_root == v_root:
return
# Union by rank
if self.rank[u_root] > self.rank[v_root]:
self.parent[v_root] = u_root
elif self.rank[u_root] < self.rank[v_root]:
self.parent[u_root] = v_root
else:
self.parent[v_root] = u_root
self.rank[u_root] += 1
def find(self, element: int) -> int:
# Perfrom path compression when finding its root node
if element != self.parent[element]:
self.parent[element] = self.find(self.parent[element])
return self.parent[element]
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
emails_ownership = {}
disjoint_set = DisjointSet(len(accounts))
for id, account in enumerate(accounts):
for i in range(1, len(account)):
email = accounts[id][i]
# If email have been already seen, then union this account with the one in the hash table
if email in emails_ownership:
disjoint_set.union(id, emails_ownership[email])
emails_ownership[email] = id
# Merge emails based on their root node in the disjoint set
merged_accounts = defaultdict(list)
for email, account in emails_ownership.items():
merged_accounts[disjoint_set.find(account)].append(email)
return [[accounts[i][0]] + sorted(emails) for i, emails in merged_accounts.items()]