leetcode 721. 账户合并

题目描述
给定一个列表 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的区别
列表字典
字典排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值