文章目录

  • 一、今日刷题
    • 1.题目
    • 2.分析
    • 3.代码
      • ①暴力破解
      • ②链表存储法
      • ③无需链表的复杂度最佳解法

一、今日刷题

1.题目

  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 图论——名流问题相关推荐

  1. 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 ...

  2. 2022.4.30—2022.6.22 学习报告

    目录 2022.4.30 2022.5.2 数据流图(Dataflow Graph) Sesssion 构建计算图 2022.5.3 Deep Label Distribution Learning ...

  3. 2022/5/30 Mybatis-Plus详解

    目录 1.Mybatis-Plus简介 2.特性 3.支持数据库 4.框架结构 5.快速开始 5.1 创建数据库mybatis_plus 5.2 搭建项目 5.2.1 创建Spring Boot工程 ...

  4. 【SRE笔记 2022.9.30 集群知识及Centos基础优化】

    SRE笔记 2022.9.30 集群内服务软件 集群模板机创建 Linux系统优化 用户优化 ssh远程连接效率提升 配置yum源 常用软件安装 安全优化 中文字符集(非必要) 时间同步 提升命令行安 ...

  5. 每日一练 — 2022.01.30

    文章目录 一,买卖股票的最佳时机 II 1,程序简介 注意: 示例 1: 示例 2: 示例 3: 提示: 2,程序代码 3,运行结果 二,分数到小数 1,程序简介 示例 1: 示例 2: 示例 3: ...

  6. 【面试专题】2022 年 30 大 JDBC 面试问题和答案

    文章目录 为什么要学习 JDBC? 2022 年顶级 JDBC 面试问题和答案 1.解释什么是JDBC? 2.什么是ResultSet? 3.你能得到一个空的ResultSet吗? 4. 解释 Res ...

  7. 创新与担当│优积科技CEO刘其东荣获中国2022年度30位最具价值EMBA校友

    日前,2022年"中国EMBA项目排行榜"发布.同济EMBA项目凭借总分154.10分,荣获综合排名全国第五. 同济EMBA校友优积建筑科技CEO刘其东,睿昂基因常务副总裁.云泰生 ...

  8. 人工智能 | ShowMeAI资讯日报 #2022.06.30

    ShowMeAI日报系列全新升级!覆盖AI人工智能 工具&框架 | 项目&代码 | 博文&分享 | 数据&资源 | 研究&论文 等方向.点击查看 历史文章列表, ...

  9. 豆粕5连跌四月季节性偏弱,铁矿石认购翻倍,甲醇05-09季节性反套2022.3.30

    <期货套利基础系列>介绍套利的基础知识: 期货套利基础第一篇:对套利的误解 第2-3篇是套利基础知识,内容来自电子书,有做过套利的人可以跳过: 期货套利基础第二篇:套利交易的基本概念 期货 ...

最新文章

  1. 取消对 null 指针“l”的引用。_C++中的引用
  2. pandas删除缺失数据(pd.dropna()方法)
  3. 学习busybox源码与移植
  4. 使用母版頁是內容如何使用CSS和javascript(轉)
  5. Linux ab 命令
  6. 一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出
  7. 惊现试衣间照片流出??
  8. php mysql 库存变负数_php解决秒杀并发入库导致的库存负数
  9. mysql 分类汇总_sql多级分类汇总实现介绍
  10. DNS服务器介绍(二)——主从复制和区域转发
  11. [设计模式] - Proxy代理模式
  12. springboot集成购买阿里的rocketmq
  13. 完全删除conime.exe
  14. 头像编辑器怎么禁用摄像头
  15. 18款室内设计风格,总有一款适合你。
  16. 程序猿头头(async与await的原理)
  17. 查看SqlServer数据库上面脚本修改信息以及修改日志
  18. Kubernetes 亲和性与反亲和性
  19. 解决MAC系统升级后虚拟机黑屏问题
  20. C++检测键盘某键是否按下

热门文章

  1. iOS - 备忘录模式(Memento Pattern)
  2. pycharm安装Translation翻译插件(中文翻译)
  3. CADisplayLink前世今生
  4. latex 参考文献
  5. JS基本数据类型 —— BigInt
  6. 分享7个素材网帮你轻松解决,新手做自媒体没播放?收益少?
  7. 零基础小白转行web前端,该怎么学?
  8. html怎么表单变成一条线,让文本框变成一条直线
  9. linux服务器查看历史,linux如何查看历史命令
  10. [DA45] 使用PageRank算法分析希拉里邮件中的人物关系