# Time: O(nlogn), n is the number of total emails, # and the max length ofemail is 320, p.s. {64}@{255} # Space: O(n) import collections class UnionFind(object): def __init__(self): self.set = [] def get_id(self): self.set.append(len(self.set)) return len(self.set)-1 def find_set(self, x): if self.set[x] != x: self.set[x] = self.find_set(self.set[x]) # path compression. return self.set[x] def union_set(self, x, y): x_root, y_root = map(self.find_set, (x, y)) if x_root != y_root: self.set[min(x_root, y_root)] = max(x_root, y_root) class Solution(object): def accountsMerge(self, accounts): """ :type accounts: List[List[str]] :rtype: List[List[str]] """ union_find = UnionFind() email_to_name = {} email_to_id = {} for account in accounts: name = account[0] for i in xrange(1, len(account)): if account[i] not in email_to_id: email_to_name[account[i]] = name email_to_id[account[i]] = union_find.get_id() union_find.union_set(email_to_id[account[1]], email_to_id[account[i]]) result = collections.defaultdict(list) for email in email_to_name.keys(): result[union_find.find_set(email_to_id[email])].append(email) for emails in result.values(): emails.sort() return [[email_to_name[emails[0]]] + emails for emails in result.values()]