leecode 面试题 17.07 婴儿名字
题目链接:https://leetcode-cn.com/problems/baby-names-lcci/
分析题意可以知道这是个并查集,新增一个size数目来维护集合数量大小就可以了(size数组只有当是父节点时才有意义)
思路:将synonyms中的相同的名字合并即可,但是names的处理就比较麻烦,对于John(15)这样一个字符串,要分离出John和15这两个字符串。同时还有一个要注意点,并查集merge的时候要注意如果find的值相同(是同一个集合的),是不需要重复加的。
class Solution:
def trulyMostPopular(self, names: List[str], synonyms: List[str]) -> List[str]:
# init
self.p = list(range(0, len(names)+100, 1))
self.size = [0] * (len(names)+100);
self.name_index_dic = {}
for i in range(len(names)):
name = names[i]
index= name.find('(')
name_size = name[index+1:-1]
name = name[:index]
self.name_index_dic[name] = i
self.size[self.name_index_dic[name]] = int(name_size)
names[i] = name
idx = len(names)
# 合并
for synonym in synonyms:
index = synonym.find(',')
name1 = synonym[1:index]
name2 = synonym[index+1:-1]
name1_id = self.name_index_dic.get(synonym[1:index])
name2_id = self.name_index_dic.get(synonym[index+1:-1])
if name1_id == None:
self.name_index_dic[name1] = idx
names.append(name1)
name1_id = idx
idx += 1
if name2_id == None:
self.name_index_dic[name2] = idx
names.append(name2)
name2_id = idx
idx += 1
# print(str(name1_id)+" "+str(name2_id))
self.__merge(name1_id, name2_id)
# 路径压缩
for i in range(len(names)):
self.__find(i)
# 得到字典序最小的名字
index_name_dict = {}
for i in range(len(names)):
if index_name_dict.__contains__(self.p[i]):
now = index_name_dict.get(self.p[i])
if names[i] < now:
index_name_dict[self.p[i]] = names[i]
else:
index_name_dict[self.p[i]] = names[i];
# 组装答案
ans = []
for key in index_name_dict:
s = index_name_dict[key] + "(" + str(self.size[key]) + ")"
ans.append(s)
# print(self.p)
return ans
p = []
size = []
name_index_dic = {}
def __find(self, x : int):
if x != self.p[x]:
self.p[x] = self.__find(self.p[x])
return self.p[x]
def __merge(self, a : int, b : int):
a = self.__find(a)
b = self.__find(b)
if a != b:
self.p[a] = b;
self.size[b] += self.size[a]