2022.3.30 图论——名流问题
文章目录
- 一、今日刷题
- 1.题目
- 2.分析
- 3.代码
- ①暴力破解
- ②链表存储法
- ③无需链表的复杂度最佳解法
一、今日刷题
1.题目
- 搜索名人
假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0 到 n - 1 标号。
在这个派对人群当中可能存在一位 “名人”。
所谓 “名人” 的定义是:其他所有 n - 1 个人都认识他/她,而他/她并不认识其他任何人。
现在你想要确认这个 “名人” 是谁,或者确定这里没有 “名人”。
而你唯一能做的就是问诸如 “A 你好呀,请问你认不认识 B呀?” 的问题,以确定 A 是否认识 B。
你需要在(渐近意义上)尽可能少的问题内来确定这位 “名人” 是谁(或者确定这里没有 “名人”)。
在本题中,你可以使用辅助函数 bool knows(a, b) 获取到 A 是否认识 B。请你来实现一个函数 int findCelebrity(n)。
派对最多只会有一个 “名人” 参加。
若 “名人” 存在,请返回他/她的编号;若 “名人” 不存在,请返回 -1。
2.分析
参考文章
给你 n 个人的社交关系(你知道任意两个人之间是否认识),然后请你找出这些人中的「名人」。
所谓「名人」有两个条件:
1、所有其他人都认识「名人」。
2、「名人」不认识任何其他人。
如果把每个人看做图中的节点,「认识」这种关系看做是节点之间的有向边,那么名人就是这幅图中一个特殊的节点:
没有一条指向其他节点的有向边;且其他所有节点都有一条指向这个节点的有向边。
即,名人节点的出度为 0,入度为 n - 1。
3.代码
函数签名:
// 可以直接调用,能够返回 i 是否认识 j
boolean knows(int i, int j);// 请你实现:返回「名人」的编号
int findCelebrity(int n) {// todo
}
①暴力破解
两层 for 循环,对所有节点逐个判断其是否满足 “名人” 的条件。
int findCelebrity(int n) {for (int cand = 0; cand < n; cand++) {int other;for (other = 0; other < n; other++) {if (cand == other) continue;// 保证其他人都认识 cand,且 cand 不认识任何其他人// 否则 cand 就不可能是名人if (knows(cand, other) || !knows(other, cand)) {break;}}if (other == n) {// 找到名人return cand;}}// 没有一个人符合名人特性return -1;
}
②链表存储法
由名人的定义可知,人群中最多有一个名人。
优化的核心:所以只要观察任意两个候选人的关系,一定能确定其中的一个人不是名人,把他排除。
以下是两节点间关系的四种情况:(红色边表示不认识,绿色边表示认识)
情况一,cand 认识 other,所以 cand 肯定不是名人,排除。(因为名人不可能认识别人)
情况二,other 认识 cand,所以 other 肯定不是名人,排除。
(情况一和情况二其实是一种情况,其中节点A认识节点B,但节点B不认识节点A,即两节点单向认识,则认识他人的节点A一定不是名人)
情况三,两节点互相认识,肯定都不是名人,可以随便排除一个。
情况四,两节点互不认识,肯定都不是名人,可以随便排除一个。(因为名人应该被所有其他人认识)
从而提出优化解法的核心:我们可以不断从候选人中选两个出来,然后排除掉一个,直到最后只剩下一个候选人,这时候再使用一个 for 循环判断这个候选人是否是货真价实的「名人」。
(想自己敲代码的但是不知道 knows函数API的内部实现)
int findCelebrity(int n) {if (n == 1) return 0;// 将所有候选人装进队列LinkedList<Integer> q = new LinkedList<>();for (int i = 0; i < n; i++) {q.addLast(i);}// 一直排除,直到只剩下一个候选人停止循环while (q.size() >= 2) {// 每次取出两个候选人,排除一个int cand = q.removeFirst();int other = q.removeFirst();if (knows(cand, other) || !knows(other, cand)) {// cand 不可能是名人,排除,让 other 归队q.addFirst(other);} else {// other 不可能是名人,排除,让 cand 归队q.addFirst(cand);}}// 现在排除得只剩一个候选人,判断他是否真的是名人int cand = q.removeFirst();for (int other = 0; other < n; other++) {if (other == cand) {continue;}// 保证其他人都认识 cand,且 cand 不认识任何其他人if (!knows(other, cand) || knows(cand, other)) {return -1;}}// cand 是名人return cand;
}
③无需链表的复杂度最佳解法
利用 other 和 cand 的交替变化,模拟了我们之前操作队列的过程,避免了使用额外的存储空间。
int findCelebrity(int n) {// 先假设 cand 是名人int cand = 0;for (int other = 1; other < n; other++) {if (!knows(other, cand) || knows(cand, other)) {// cand 不可能是名人,排除// 假设 other 是名人cand = other;} else {// other 不可能是名人,排除// 什么都不用做,继续假设 cand 是名人}}// 现在的 cand 是排除的最后结果,但不能保证一定是名人for (int other = 0; other < n; other++) {if (cand == other) continue;// 需要保证其他人都认识 cand,且 cand 不认识任何其他人if (!knows(other, cand) || knows(cand, other)) {return -1;}}return cand;
}
时间复杂度为 O(N),空间复杂度为 O(1)
2022.3.30 图论——名流问题相关推荐
- Tue Jun 28 2022 15:30:29 GMT+0800 (中国标准时间) 日期格式化
1. Tue Jun 28 2022 15:30:29 GMT+0800 (中国标准时间) 转换为 2022-06-28 15:30:29 代码如下 const d = new Date(Tue Ju ...
- 2022.4.30—2022.6.22 学习报告
目录 2022.4.30 2022.5.2 数据流图(Dataflow Graph) Sesssion 构建计算图 2022.5.3 Deep Label Distribution Learning ...
- 2022/5/30 Mybatis-Plus详解
目录 1.Mybatis-Plus简介 2.特性 3.支持数据库 4.框架结构 5.快速开始 5.1 创建数据库mybatis_plus 5.2 搭建项目 5.2.1 创建Spring Boot工程 ...
- 【SRE笔记 2022.9.30 集群知识及Centos基础优化】
SRE笔记 2022.9.30 集群内服务软件 集群模板机创建 Linux系统优化 用户优化 ssh远程连接效率提升 配置yum源 常用软件安装 安全优化 中文字符集(非必要) 时间同步 提升命令行安 ...
- 每日一练 — 2022.01.30
文章目录 一,买卖股票的最佳时机 II 1,程序简介 注意: 示例 1: 示例 2: 示例 3: 提示: 2,程序代码 3,运行结果 二,分数到小数 1,程序简介 示例 1: 示例 2: 示例 3: ...
- 【面试专题】2022 年 30 大 JDBC 面试问题和答案
文章目录 为什么要学习 JDBC? 2022 年顶级 JDBC 面试问题和答案 1.解释什么是JDBC? 2.什么是ResultSet? 3.你能得到一个空的ResultSet吗? 4. 解释 Res ...
- 创新与担当│优积科技CEO刘其东荣获中国2022年度30位最具价值EMBA校友
日前,2022年"中国EMBA项目排行榜"发布.同济EMBA项目凭借总分154.10分,荣获综合排名全国第五. 同济EMBA校友优积建筑科技CEO刘其东,睿昂基因常务副总裁.云泰生 ...
- 人工智能 | ShowMeAI资讯日报 #2022.06.30
ShowMeAI日报系列全新升级!覆盖AI人工智能 工具&框架 | 项目&代码 | 博文&分享 | 数据&资源 | 研究&论文 等方向.点击查看 历史文章列表, ...
- 豆粕5连跌四月季节性偏弱,铁矿石认购翻倍,甲醇05-09季节性反套2022.3.30
<期货套利基础系列>介绍套利的基础知识: 期货套利基础第一篇:对套利的误解 第2-3篇是套利基础知识,内容来自电子书,有做过套利的人可以跳过: 期货套利基础第二篇:套利交易的基本概念 期货 ...
最新文章
- 取消对 null 指针“l”的引用。_C++中的引用
- pandas删除缺失数据(pd.dropna()方法)
- 学习busybox源码与移植
- 使用母版頁是內容如何使用CSS和javascript(轉)
- Linux ab 命令
- 一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出
- 惊现试衣间照片流出??
- php mysql 库存变负数_php解决秒杀并发入库导致的库存负数
- mysql 分类汇总_sql多级分类汇总实现介绍
- DNS服务器介绍(二)——主从复制和区域转发
- [设计模式] - Proxy代理模式
- springboot集成购买阿里的rocketmq
- 完全删除conime.exe
- 头像编辑器怎么禁用摄像头
- 18款室内设计风格,总有一款适合你。
- 程序猿头头(async与await的原理)
- 查看SqlServer数据库上面脚本修改信息以及修改日志
- Kubernetes 亲和性与反亲和性
- 解决MAC系统升级后虚拟机黑屏问题
- C++检测键盘某键是否按下