题目![在这里插入图片描述](https://img-blog.csdnimg.cn/20190418121134124.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYWJlbnNodQ==,size_16,color_FFFFFF,t_70)
就是说给出一系列人物的名字和邮箱,里面的人可能重名,但要将列表合并,将同人物的邮箱合并起来。
思路及代码
第一步,我们先假定有以下的列表:
[
["John", "johnsmith@mail.com", "john00@mail.com"], # Account 0
["John", "johnnybravo@mail.com"], # Account 1
["John", "johnsmith@mail.com", "john_newyork@mail.com"], # Account 2
["Mary", "mary@mail.com"] # Account 3
]
接下来,构建一个将电子邮件映射到帐户列表的emails_accounts_map,该列表可用于跟踪链接到哪个帐户的电子邮件。这就是我们的图像。
得到一个映射,关于邮箱对应的账户,就需要合并。
# emails_accounts_map of email to account ID
{
"johnsmith@mail.com": [0, 2],
"john00@mail.com": [0],
"johnnybravo@mail.com": [1],
"john_newyork@mail.com": [2],
"mary@mail.com": [3]
}
python DFS遍历:
class Solution(object):
def accountsMerge(self, accounts):
from collections import defaultdict
visited_accounts = [False] * len(accounts)
emails_accounts_map = defaultdict(list)
res = []
# Build up the graph.
for i, account in enumerate(accounts):
for j in range(1, len(account)):
email = account[j]
emails_accounts_map[email].append(i)
# DFS code for traversing accounts.
def dfs(i, emails):
if visited_accounts[i]:
return
visited_accounts[i] = True
for j in range(1, len(accounts[i])):
email = accounts[i][j]
emails.add(email)
for neighbor in emails_accounts_map[email]:
dfs(neighbor, emails)
# Perform DFS for accounts and add to results.
# 查找所有的账户,使用深度优先算法,遍历所有的账户,每个账户只查找一遍,然后即可实现合并。
for i, account in enumerate(accounts):
if visited_accounts[i]:
continue
name, emails = account[0], set()
dfs(i, emails)
res.append([name] + sorted(emails))
return res
高效代码
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
N = len(accounts)
acc_graph = [set() for _ in range(N)]
emails_map = {}
for i, (name, *emails) in enumerate(accounts):
uniques = []
for email in emails:
if email in emails_map:
j = emails_map[email]
acc_graph[i].add(j)
acc_graph[j].add(i)
else:
emails_map[email] = i
uniques.append(email)
accounts[i] = name, uniques
visited = [False]*N
out = []
for i in range(N):
if visited[i]:
continue
visited[i], stack = True, [i]
account = []
while stack:
i = stack.pop()
account.extend(accounts[i][1])
for ch in acc_graph[i]:
if not visited[ch]:
visited[ch] = True
stack.append(ch)
account.sort(reverse=True)
account.append(accounts[i][0])
account.reverse()
out.append(account)
return out