721. 账户合并
给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails 表示该账户的邮箱地址。
现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于同一个人。请注意,即使两个账户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的账户,但其所有账户都具有相同的名称。
合并账户后,按以下格式返回账户:每个账户的第一个元素是名称,其余元素是按顺序排列的邮箱地址。账户本身可以以任意顺序返回。
并查集+哈希表
注意看一下数据
- accounts的长度将在[1,1000]的范围内。
说明n²复杂度的代码基本可以过
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
n = len(accounts)
parent = list(range(n))
def find(index):
if index != parent[index]:
parent[index] = find(parent[index])
return parent[index]
def union(index1,index2):
parent[find(index2)] = find(index1)
for i in range(n):
accounts[i] = [accounts[i][0]] + list(set(accounts[i][1:]))
visited = set()
dic = collections.defaultdict(set)
for i in range(n-1):
for j in range(i+1,n):
leni,lenj = len(accounts[i]),len(accounts[j])
lensum = len(set(accounts[i][1:]+accounts[j][1:]))
if lensum^(leni+lenj-2):
union(i,j)
for i in range(n):
if i not in visited:
dic[i] = set(accounts[i][1:])
for j in range(i+1,n):
if j not in visited and find(i)==find(j):
visited.add(j)
dic[i] |= set(accounts[j][1:])
ans =[]
for key,value in dic.items():
stand = [accounts[key][0]] + sorted(list(value))
ans.append(stand)
return ans
时间复杂度O(n²)
优化:
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
def union(self, index1: int, index2: int):
self.parent[self.find(index2)] = self.find(index1)
def find(self, index: int) -> int:
if self.parent[index] != index:
self.parent[index] = self.find(self.parent[index])
return self.parent[index]
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
emailToIndex = dict()
emailToName = dict()
for account in accounts:
name = account[0]
for email in account[1:]:
if email not in emailToIndex:
emailToIndex[email] = len(emailToIndex)
emailToName[email] = name
uf = UnionFind(len(emailToIndex))
for account in accounts:
firstIndex = emailToIndex[account[1]]
for email in account[2:]:
uf.union(firstIndex, emailToIndex[email])
indexToEmails = collections.defaultdict(list)
for email, index in emailToIndex.items():
index = uf.find(index)
indexToEmails[index].append(email)
ans = list()
for emails in indexToEmails.values():
ans.append([emailToName[emails[0]]] + sorted(emails))
return ans