携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 24 天,点击查看活动详情
婴儿名字
原题地址
每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量。有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来。给定两个列表,一个是名字及对应的频率,另一个是本质相同的名字对。设计一个算法打印出每个真实名字的实际频率。注意,如果 John 和 Jon 是相同的,并且 Jon 和 Johnny 相同,则 John 与 Johnny 也相同,即它们有传递和对称性。
在结果列表中,选择 字典序最小 的名字作为真实名字。
示例:
输入:names = ["John(15)","Jon(12)","Chris(13)","Kris(4)","Christopher(19)"],
synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]
输出:["John(27)","Chris(36)"]
提示:
names.length <= 100000
思路分析
- 首先将 names 中的数据拆分存储到一个对象
nameMap中,以名字为key,人数为value值存储; - 然后将
synonyms中名字的本质找出来,此时我们定义一个UnionSet来存储本质名字,其中data表示本质名字的数据,size表示其长度; - 在
UnionSet中定义一个find方法来寻找最小字典序的名字,然后定义一个union方法,将最小字典序的名字和当前名字对应起来; - 遍历
nameMap,若不在集合中,则单独处理,最后的数据即为当前的数据;若在集合中,则需要将对应的名字找出来然后求和得到最后的值,此值记为resMap; - 最后返回结果为数组,因此遍历
resMap,将数据组装好存储到res中返回即可。
AC 代码
/**
* @param {string[]} names
* @param {string[]} synonyms
* @return {string[]}
*/
var trulyMostPopular = function(names, synonyms) {
const nameMap = {}
const resMap = {}
let synonymsSet = new UnionSet()
const res = []
names.forEach(item => {
const strs = item.split('(')
nameMap[strs[0]] = Number(strs[1].substring(0, strs[1].length - 1))
})
synonyms.forEach(item => {
const sub = item.substring(1, item.length - 1).split(',')
synonymsSet.union(sub[0], sub[1])
})
for (n in nameMap) {
if (synonymsSet.data[n] === undefined){ // 不在并查集中的名字单独列出
resMap[n] = nameMap[n]
continue
}
let name = synonymsSet.find(n)
if (resMap[name] == undefined) resMap[name] = nameMap[n]
else resMap[name] += nameMap[n]
}
for (item in resMap) { //数组输出
res.push(item + '(' + resMap[item] + ')')
}
return res
};
class UnionSet {
constructor () {
this.data = {};
this.size = 0;
}
find (item) {
while (this.data[item] != item) item = this.data[item]
return item
}
union(a, b) {
if (this.data[a] === undefined) {
this.data[a] = a;
this.size++;
}
if (this.data[b] === undefined) {
this.data[b] = b;
this.size++;
}
const dataA = this.find(a)
const dataB = this.find(b)
if (dataA < dataB) this.data[dataB] = dataA
else this.data[dataA] = dataB
}
}
结果:
- 执行结果: 通过
- 执行用时:400 ms, 在所有 JavaScript 提交中击败了50.00%的用户
- 内存消耗:69.8 MB, 在所有 JavaScript 提交中击败了66.67%的用户
- 通过测试用例:36 / 36