题目描述:
给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails 表示该账户的邮箱地址。
现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于同一个人。请注意,即使两个账户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的账户,但其所有账户都具有相同的名称。
合并账户后,按以下格式返回账户:每个账户的第一个元素是名称,其余元素是 按字符 ASCII 顺序排列 的邮箱地址。账户本身可以以 任意顺序 返回。
示例:
输入:accounts = [[“John”, “johnsmith@mail.com”, “john00@mail.com”], [“John”, “johnnybravo@mail.com”], [“John”, “johnsmith@mail.com”, “john_newyork@mail.com”], [“Mary”, “mary@mail.com”]]
输出:[[“John”, ‘john00@mail.com’, ‘john_newyork@mail.com’, ‘johnsmith@mail.com’], [“John”, “johnnybravo@mail.com”], [“Mary”, “mary@mail.com”]]
解释:
第一个和第三个 John 是同一个人,因为他们有共同的邮箱地址 “johnsmith@mail.com”。
第二个 John 和 Mary 是不同的人,因为他们的邮箱地址没有被其他帐户使用。
可以以任何顺序返回这些列表,例如答案 [[‘Mary’,‘mary@mail.com’],[‘John’,‘johnnybravo@mail.com’],
[‘John’,‘john00@mail.com’,‘john_newyork@mail.com’,‘johnsmith@mail.com’]] 也是正确的。
题解:
该题非常经典,是一道并查集的题目。题解中用到多种数据结构,集合,哈希表,还要区分list的append和extend的方法,然后如何创建列表字典。ASCII 顺序排列用sort实现,其余具体思路见注释
from collections import defaultdict
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
#1.我们只能根据邮箱名相同来进行合并,如何判断邮箱名是否相同那么就需要一个哈希表作为介质。
# 找到相同了后,该如何合并呢?这个时候就需要哈希表的value存位置索引才行
email_dict = {}
uf = Unionfind(accounts)
row = len(accounts)
for i in range(0,row):
for j in range(1,len(accounts[i])):
if accounts[i][j] not in email_dict:
email_dict[accounts[i][j]] = i
else:
uf.union(i,email_dict[accounts[i][j]])
#2.把根节点作为key,元素作为value构成一个字典,方便下一步合并为一个用户
# 创建列表字典,即初始化的value为list
graph = collections.defaultdict(list)
for i in range(0,row):
parent = uf.find(i)
graph[parent].append(i)
#3.合并同一个根节点的用户的邮箱
res = []
for idx, idx_list in graph.items():
cur = [accounts[idx][0]]
#用集合这个数据结构,避免加入重复元素
emails = set()
for i in idx_list:
emails.update(accounts[i][1:])
emails = list(emails) #将集合转为列表
emails.sort()
#extend()用于在列表末尾追加另一个序列中的多个值,输入对象为元素队列
cur.extend(emails)
res.append(cur)
return res
class Unionfind:
def __init__(self,accounts):
self.root = []
length = len(accounts)
self.root = [-1]*length
for i in range(0,length):
self.root[i] = i
def find(self,x):
if self.root[x] == x:
return x
else:
#用了递归
self.root[x] = self.find(self.root[x])
return self.root[x]
def union(self,x,y):
rootx = self.find(x)
rooty = self.find(y)
if rootx != rooty:
self.root[rootx] = rooty
refer:
题解
Python列表操作中extend和append的区别
列表字典
字典排序