题目难度: 中等

原题链接

今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

  • 每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量。
  • 有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来。
  • 给定两个列表,一个是名字及对应的频率,另一个是本质相同的名字对。
  • 设计一个算法打印出每个真实名字的实际频率。
  • 注意,如果 John 和 Jon 是相同的,并且 Jon 和 Johnny 相同,则 John 与 Johnny 也相同,即它们有传递和对称性。
  • 在结果列表中,选择字典序最小的名字作为真实名字。
  • names.length <= 100000

题目样例

示例

输入

names = ["John(15)","Jon(12)","Chris(13)","Kris(4)","Christopher(19)"], synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]

输出

["John(27)","Chris(36)"]

题目思考

  1. 如何得到每个名字的真实名字?
  2. 需要额外记录什么信息?

解决方案

思路

  • 分析题目, 我们需要根据提供的名字对信息, 得到所有具有相同真实名字的名字集合, 然后累计其频率并输出
  • 这里我们可以利用经典的并查集算法, 就是将元素进行分类, 相同的放在同一个集合中
  • 当然靠暴力模拟也可以做到归类, 但是那样会涉及到耗时巨大的集合求并集和循环判断等, 效率过低; 而并查集可以做到每次操作只需要 O(logN)甚至更短的时间
  • 并查集的思路很简单, 具体步骤如下:
    1. 首先我们需要定义一个字典 pre, pre[x]表示 x 的祖先, 如果两个元素具有相同祖先, 就表示它们在同一个集合中. 可以把祖先 pre[x] 想象成一个树的根节点, 那么 x 就是树中的一个节点(可能是根节点本身)
    2. 然后定义一个 find 方法, 查找当前元素的祖先, 如果祖先不存在的话就把自身当做祖先. 这里用到了路径压缩的优化, 就是说当发现自己的祖先不是自身的时候, 就尝试把自己的祖先设置为自己的当前祖先的祖先, 从而降低树的高度, 加快之后的查找过程
    3. 最后定义一个 union 方法, 用于合并两个元素. 这里的思路也很简单, 就是找到各自的祖先, 然后将其中一个的祖先的祖先设置为另外一个祖先即可, 等于就把两个树合并在了一起
  • 注意这道题相比传统并查集多了两个条件, 一是要求祖先最小, 二是需要求频率之和
  • 针对第一个需求, 我们可以更改 union 方法, 将字典序较大的祖先指向字典序较小的祖先, 这样就能保证最终的祖先一定是字典序最小的
  • 针对第二个需求, 我们可以额外引入一个计数字典, 记录祖先的频率, 每次遍历到一个新名字, 其对应的祖先的频率就加上当前的频率
  • 然后最终再遍历计数字典, 将 kv 转换成结果的格式即可
  • 下面的代码中对每个步骤都有注释, 方便大家理解

复杂度

  • 时间复杂度 O((N+M)logN): 假设 N 为名字个数, M 为名字对个数, 那么需要分别循环 M 和 N 合并和统计频率, 每次 find/union 操作需要 logN 时间, 所以总共复杂度就是 O((N+M)logN)
  • 空间复杂度 O(N): pre 字典中存 N 个名字

代码

class Solution:def trulyMostPopular(self, names: List[str], synonyms: List[str]) -> List[str]:# 并查集变种, 先找到所有相同的名字, 然后再统计数字# 注意祖先需要是字典序最小的, 所以需要稍微改动union逻辑pre = {}def find(x):if x not in pre:pre[x] = xelif pre[x] != x:pre[x] = find(pre[x])return pre[x]def union(x, y):px = find(x)py = find(y)# 保证祖先的字典序更小if px > py:pre[px] = pyelse:pre[py] = pxfor s in synonyms:# parse两个名字, 并合并x, y = s[1:-1].split(",")union(x, y)cnts = collections.defaultdict(int)for t in names:i = t.find("(")# parse当前名字和频率name = t[:i]cnt = int(t[i + 1 : t.find(")")])# 累加到祖先对应的频率中cnts[find(name)] += cntres = []for k in cnts:# 转换成结果要求的格式res.append(k + "(" + str(cnts[k]) + ")")return res

大家可以在下面这些地方找到我~

程序员面试金典 - 面试题 17.07. 婴儿名字相关推荐

  1. 程序员面试金典 - 面试题 17.07. 婴儿名字(并查集)

    1. 题目 每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量. 有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来. 给定两个 ...

  2. 程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)

    文章目录 1. 题目 2. 解题 2.1 超时解 2.2 二分查找 1. 题目 有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上.出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一 ...

  3. 程序员面试金典 - 面试题 17.06. 2出现的次数(找递推规律)

    1. 题目 编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数. 示例: 输入: 25 输出: 9 解释: (2, 12, 20, 21, 22, 23, 24, 25)(注意 22 ...

  4. 程序员面试金典 - 面试题 17.22. 单词转换(BFS)

    1. 题目 给定字典中的两个词,长度相等. 写一个方法,把一个词转换成另一个词, 但是一次只能改变一个字符. 每一步得到的新词都必须能在字典中找到. 编写一个程序,返回一个可能的转换序列.如有多个可能 ...

  5. 程序员面试金典 - 面试题 17.15. 最长单词(排序+递归)

    1. 题目 给定一组单词words,编写一个程序,找出其中的最长单词,且该单词由这组单词中的其他单词组合而成. 若有多个长度相同的结果,返回其中字典序最小的一项,若没有符合要求的单词则返回空字符串. ...

  6. 程序员面试金典 - 面试题 05.07. 配对交换(位运算)

    1. 题目 配对交换.编写程序,交换某个整数的奇数位和偶数位,尽量使用较少的指令(也就是说,位0与位1交换,位2与位3交换,以此类推). 示例1:输入:num = 2(或者0b10)输出 1 (或者 ...

  7. [Leetcode][程序员面试金典][面试题17.13][JAVA][恢复空格][动态规划][Trie][字符串哈希]

    [问题描述][中等] [解答思路] 1. 动态规划 动态规划流程 第 1 步:设计状态 dp[i] 表示字符串的前 i 个字符的最少未匹配数. 第 2 步:状态转移方程 假设当前我们已经考虑完了前 i ...

  8. 程序员面试金典 - 面试题 17.26. 稀疏相似度(哈希map)

    1. 题目 两个(具有不同单词的)文档的交集(intersection)中元素的个数除以并集(union)中元素的个数,就是这两个文档的相似度. 例如,{1, 5, 3} 和 {1, 7, 2, 3} ...

  9. 程序员面试金典 - 面试题 17.25. 单词矩阵(Trie树+DFS回溯,hard)

    1. 题目 给定一份单词的清单,设计一个算法,创建由字母组成的面积最大的矩形,其中每一行组成一个单词(自左向右),每一列也组成一个单词(自上而下). 不要求这些单词在清单里连续出现,但要求所有行等长, ...

最新文章

  1. leetcode算法题--最佳买卖股票时机含冷冻期★
  2. Apache认证、授权和访问控制
  3. Yes, Prime Minister 打表找规律-质数
  4. gtone eclipse plugin install
  5. PyTorc 1.0 中文文档:扩展PyTorch
  6. Java并发编程之调度线程池
  7. opencv 识别机车
  8. java 设置主线程_Java线程编程中的主线程讲解
  9. 用友U8 13.0运维及操作手册全版
  10. ToStringBuilder介绍
  11. Linux使用命令安装vim编辑器
  12. 【Java】通讯录管理系统小项目
  13. 学习cola DDD 架构遇到的问题 在start模块的pom文件添加依赖
  14. Android Studio 支持安卓手机投屏
  15. unity光圈旋转效果
  16. fft 估计载波频率程序_fft频率估计
  17. openwrt 恢 复 出厂设置
  18. php 微信分享不显示主题,Wordpress微信分享不显示description和图标
  19. 中国团队夺得MegaFace百万人脸识别冠军,精度98%再创记录,论文代码+数据全开源
  20. 【Android】(二)SQLite可视化工具SQLiteStudio的用法

热门文章

  1. 学习潘海东博士的《潮汐调和分析原理和应用》
  2. 2022年全球市场卫浴五金制品总体规模、主要企业、主要地区、产品和应用细分研究报告
  3. 农村土地确权之成果展示 —— 地块签章图
  4. 【题解】CF1770E Koxia and Tree
  5. 130家!2020年度智能制造、工业软件、工业大数据企业排行榜!
  6. Vue:字符串模板和dom模板的区别
  7. 一个破解游戏双开的问题
  8. Y480Y580 刷slic2.1全自动教程
  9. 虚拟机添加硬盘后,提示由于管理员设置的策略,该磁盘属于脱机状态解决方案
  10. youtube_dl urlopen error EOF occurred in violation of protocol (_ssl.c:nnn) 错误的解决方法