我去,这个题对于刚学并查集的我来说还是挺难的,记录一下!(这个查询方法太慢了)
from collections import defaultdict
# names = ["John(15)", "Jon(12)", "Chris(13)", "Kris(4)", "Christopher(19)"]
# synonyms = ["(Jon,John)", "(John,Johnny)", "(Chris,Kris)", "(Chris,Christopher)"]
class UnionFind:
def __init__(self, names_: []):
self.parent = {}
# 初始化数组
for name in names_:
# parent中存放name(key)和name(value)的是以键值对方式存放的
# 这样一来就可以和以数组的方式i和arr[i]并查方式一样了,也就是说
# 现在我们可以以key作为i(即节点本身的信息),以value作为arr[i](即节点的根节点信息)方式存放
# 初始化时key为本身(i),value也为本身(arr[i])
self.parent[name] = name
def find(self, p):
"""
查找 p 节点的根节点
:param p:待查找的节点
:return:返回根节点的标记(这里即字典中的value)
"""
while p != self.parent[p]:
# 查找当前节点的爷爷节点的组别
p = self.parent[self.parent[p]]
return p
def union(self, p, q):
"""
合并操作
:param p:
:param q:
:return:
"""
# 如果要合并的元素有一个不在parent列表中,则结束
if p not in self.parent or q not in self.parent:
return
# 判断p和q是否指向相同的根节点
p_root = self.find(p)
q_root = self.find(q)
if p_root == q_root:
return
# 如果p所在的树小于q所在的树,则将p所在的树合并到q所在的树
# TODO:这里字典的操作和数组有区别
if p_root < q_root:
# 更改q_root对应的value值,即将小树挂载到大树上
self.parent[q_root] = p_root
if p_root > q_root:
self.parent[p_root] = q_root
class Solution(object):
"""
我们将name(每一个name,例如john和jon,以及其对应的次数都存放在freq_map中)
将name放在并查集中合并,然后再赋予 “相同” name的次数,存放在 res_map 中
"""
def trulyMostPopular(self, names, synonyms)->list:
"""
:param names:
:param synonyms:
:return:
"""
# 以defaultdict第一字典时当字典里的key不存在但被查找时,返回的是一个默认值
freq_map = defaultdict(int)
# 将数据解析出来
for freq_name in names:
# names:"john(12)"这种数据格式
name, freq_str = (part.strip(")") for part in freq_name.split("("))
# 把name和对应的名字的频率放入字典
freq_map[name] = int(freq_str)
# 然后初始化并查集,dict/defaultdict.keys()返回一个字典所有的键
uf = UnionFind(freq_map.keys())
# 然后是并操作,synonyms保存的是“相同”name的列表,解析出来后立即将其连接起来
# 并且这些name也在names列表中,并且已经先初始化了uf对象
for pair_str in synonyms:
a, b = (n.strip(")").strip("(") for n in pair_str.split(","))
uf.union(a, b)
# 生成最终结果
result = []
res_map = defaultdict(int)
# freq_map中存放的是name和对应的频次例如:john: 12
for name_, freq in freq_map.items():
# res_map[uf.find(name_)] += freq,
# 其中uf.find(name_)是找到当前节点的根节点,
res_map[uf.find(name_)] = res_map[uf.find(name_)] + freq
for name_, freq in res_map.items():
# result保存的结果应当是john(12)这种形式的,所以下面append操作里面的是这种形式
result.append("{}({})".format(name_, freq))
return result
if __name__ == "__main__":
names = ["John(15)", "Jon(12)", "Chris(13)", "Kris(4)", "Christopher(19)"]
synonyms = ["(Jon,John)", "(John,Johnny)", "(Chris,Kris)", "(Chris,Christopher)"]
s = Solution()
result_ = s.trulyMostPopular(names, synonyms)
print(result_)