leetcode(25)并查集系列题目
684. 冗余连接
- 最开始,每个人都是自己的爹。
因为所有人名字都是自然数1,2,3,4。构建一个【爹们】数组,parents,就直接把第一位朋友1的爹放在index为1的位置,第二位朋友2的爹放在index为2的位置,排排站好 - 如果某个人的爹就是自己,那他就不可能再有别的爹了。
所以,去parents找第n位朋友的爹,如果parents[x] == x,就说明这位朋友没有别的爹。 - 也就是说,如果parents[x] != x,它的爹是别人!!那我们就再去找那个人,看看那个人还有没有别的爹,一直找到根源为止(最高老爹)。
- 然后就是根据规则,数组里每一对儿,都开始相认。相认前,先分别找爹。如果两个人爹不一样,就让他们相认。这里比如让后面的人认前面的人为爹。
- 如果发现两人的爹是同一个人,说明他们本来就有一个爹了,都和这个爹相连接(即两个节点原本就是联通的),但是现在又要让他们加上一层连接,就多余了。于是答案就是这两个数。即返回导致形成环的一组边
class Solution:
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
size = len(edges)
father = list(range(size + 1)) # 注意+1
def find(num):
while father[num] != num:
num = father[num]
return num
def union(num1, num2):
root1 = find(num1)
root2 = find(num2)
if root1 == root2:
return True
else:
father[root2] = root1
return False
for src, dst in edges:
if union(src, dst):
return [src, dst]
721. 账户合并
方法一:直接求集合是否有交集
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
from collections import defaultdict
# if not accounts:return
dic = defaultdict(list)
for acc in accounts:
name = acc[0]
email = set(acc[1:])
dic[name].append(email) # 合并到同一个名字下面
# print(dic[name][:-1])
for e in dic[name][:-1]: # 没加入当前set之前的邮箱集合
if e & email: # 如果有共同邮箱
dic[name].remove(e) # 删除之前的
# print(dic[name][-1])
# print(e)
dic[name][-1].update(e) # 合并两个具有共同邮箱的集合
# print(dic[name][-1])
res = []
# print(dic)
for k, v in dic.items():
for tmp in v:
res.append([k] + list(sorted(tmp)))
return res
方法二:并查集
参考资料:
Python3 【全国最菜找爹游戏】