逛技术平台的时候,刷到一道算法题,一眼看去,就被其开头吸引了:

摘自知乎某 Google 分布式大神的一道题,技术是Google内部出的有史以来最难的一道题

嗯,距离下班还有一段时间,就看看把。

题目

包括你在内的一群计算机科学家被一帮邪恶的『数学毁灭教』的教徒们抓住了,各自分开关押,人数未知。现在,你被允许写一封邮件给狱长,狱长会帮你把这封邮件转发给其它所有人。在此之后,你们之间的交流将变得十分有限:

从明天起,每天上午,每个人必须写下一个0或者一个1,然后由狱长收集。狱长收到所有人的信息后,在心中将你们排成一个圆(顺序可以由狱长任意决定,每天都可能不一样)。
然后在当天下午,狱长会把每个人写下的那一位数字分别交给圆中位于这个人顺时针方向的下一个人。
如果某天,某位计算机科学家可以自信地把被抓的人的总数告诉狱长,并且答案正确,则全体释放;若答案错误则全体处死。

问:
(Easy)提供一个方案,使得至少99%概率下所有人能释放。
(Hard)提供一个确定性方案,使得保证所有人都能释放。

注意:狱长可能随机决定每个人在圆中的排列顺序,也可能根据你写给大家的邮件内容,或是当天大家写的数字等等,来排出某个有针对性的顺序。
注意2:所有人都是长生不老的。:P

其他人的分析

一开始想了一会,思路有限,于是点开看评论,发现有一条疑似答案的:

一个简单的解决方案,写信的人每天写1,其他人一开始写0,后面收到什么写什么。当写信的人连续N天(N表示1的个数)收到1的时候。那么根据概率论,是能得到一个近似值。后面再写0。可以来回验证概率的准确性。时间是无限的。那么概率会无限接近于真相。也就是100%。问题在于这种方案永远无法得到一个100的准确率

仔细想来不可行,原因在于该方案的基础是概率论,也就是随机性,但是题目中典狱长开了上帝视角,可以决定抛骰子的概率,随机性这一条就不符合了。也就是说,典狱长在一开始知道你的策略之后,可以做针对。

反例,假设A为写信者,B为第一天A的下线,C为第二天A的下线。从第一天开始,总是把A的【前一天】的下线作为【下一天】A的上线,则该组中永远只有不超过2个1,且A每天收到的都是1。

D1
Xj/0 -> A/1 -> B/0 -> C/0 -> Xi/0D2
Xj/0 -> B/1 -> A/1 -> C/0 -> Xi/0D3
Xj/0 -> C/1 -> A/1 -> B/0 -> Xi/0D4
Xj/0 -> B/1 -> A/1 -> C/0 -> Xi/0

可以发现,D2-D4可以无限循环下去,形成死局。

我的分析

上面的答案虽然不正确,但是无疑打开了我的思路。顺着想下去,发现似乎有戏。

首先,可以做一个合理的假设:数学家的人数是有限的,为M。这里给个预估值100人以内。(这个预估值是为了便于理解,取一千,一万都可以,有穷的就行。如果是无穷的话本身题目就无解。)

其次,问题的关键在于,如何在有恶意干扰的情况下,在组内传播有效信息,即这种传播应该是像病毒一样具有强扩散性的。

分析这条规则:写信的人每天写1,其他人一开始写0,后面收到什么写什么。
可以把写信人理解为1的源头,标为黑色,其他人一开始都是0,为白色。写信人可以生产黑色,其他人只能传递黑色,只有当写信人接触到一个新的其他人,组内才会多一个黑色。
在随机性成立的条件下,黑色会以一个固定的速度生长并传播,但是由于典狱长的存在,他可以掐断黑色的生长。

那么把规则稍稍修改:

  • 规则1:写信的人(起个名字:智能人)每天写1,其他人(起个名字:沉睡人)一开始写0,如果沉睡人收到1后,就被唤醒,变成智能人,也开始写1,否则的话还是收到什么写什么,这条规则在一开始告诉所有人。
  • 规则2:写信的人预估总人数为M,并告诉所有人。

这里先说下什么是智能人,沉睡人:

  • 智能人:知晓其他智能人的存在,即知晓当前组内智能人的人数。
  • 沉睡人:啥也不知道,只能根据一开始的规则行动。

至于这种特性怎么来的,下面会说到。在此规则下,再加上后续的补充规则3,可以分析得到:不管典狱长怎么捣鬼,最终所有的沉睡人都会被唤醒,变成智能人,即知道组内人数。

进一步分析

举例,第一天后,即第二天早上,A,B都是智能人,继续写1,然后典狱长坏坏地在排序上做了手脚。第三天早上,有两种情况:
1.多了1个智能人。(AB相邻,A->B->C或者B->A->C,唤醒了C)
2.多了2个智能人。(AB不相邻,A->C->B->D或者B->C->A->D,唤醒了C,D)

也就是说,唤醒的速度是[1,n],n为当前轮次组内智能人的数量。即每轮至少有一个人会被唤醒,最多有n个人被唤醒。

那么,现在的问题是,如何确定有几个新人被唤醒了呢?下面说:

第一天

  • 初始状态:组内有(确定的)1个智能人A。
  • 操作:第一轮唤醒。即A写1,其他人写0。

第二天

  • 前一天结果分析:A可以根据第二天收到的数,1或者0,知道组内是只有1人或者至少2人。

    • 第一种情况:收到1,这个1必然只能来自A自己,即组内只有1人,所有智能人都已经被唤醒,游戏结束。
    • 第二种情况:收到0,组内至少有2人或更多,且此时场上有两个智能人A,B。
    • 上述是A的视角,即A可以凭借信息做出的分析。那B呢?同样地,只要他第二天收到了1,则必然是情况二,此时A和B信息对等,即相互知道彼此的存在。下面就对情况二再作分析。
  • 初始状态:组内有(确定的)2个智能人A,B。
  • 操作:第二轮唤醒。即A,B写1,其他人收到什么写什么。

第三天

  • 前一天结果分析:此时,A,B无法根据收到的数,1或者0,确切知道新唤醒的智能人个数。那么,他们的任务就是:去确定经过第二天(第二轮唤醒)后,组内的确切智能人人数。
  • 初始状态:组内有3-4个智能人。
  • 操作:第二轮唤醒后的第一次交流。其他人都不说话,首先A来说,我昨天收到的是0还是1。(至于这个怎么说,后面会详解)经过交流之后,B知道了A写的数。

第四天

  • 操作:第二轮唤醒后的第二次交流。其他人都不说话,然后B来说,我昨天收到的是0还是1。经过交流之后,A知道了B写的数。此时,A,B的信息再次对等,交流环节结束,可以开始分析。(第二轮唤醒前,组内有两个智能人,所以需要两次交流。)
  • 结果分析:如果A,B一共收到了:
    • 0个1:上一轮唤醒了2个智能人。
    • 1个1:上一轮唤醒了1个智能人。
    • 2个1:上一轮唤醒了0个智能人,所有人都被唤醒,上一轮智能人数就是组内人数!

这个分析挺显而易见的,就不展开了。这里说一下怎么实现交流:“A来说,我昨天收到的是0还是1”。道理和上面说的规则1类似,规定当前轮次为A的交流轮次,只允许A发言1或0,其他人都发0,如果其他人收到了1,就一直是1。
当轮次足够多时,比如预估总人数100人以内,那么运行100次以上后,组内所有人都会传播为A的发言。这时候B就知道了A的信息。这里有一个比较tricky的地方,就是一开始,写信人A把总人数的预估值M设置为多少,理论上说,当M无穷大时,即A至少连续M-1天收到1时,此时可以认为信息已经充分传播。

那么,此时的C或者D,和A,B信息对等吗?答案是对等的。因为两次交流的结果,是全组人都知道的,C或者D必然知道了A,B写的数,也能推理出第二轮新唤醒的人数,也能知道此时组内智能人的总人数!

第五天

  • 然后,就又返回到唤醒的轮次,组内的3个或者4个智能人,再做一遍之前的唤醒操作。然后是唤醒后的交流操作,最后最分析。这样循环往复,直到上一轮唤醒了0个智能人,GameOver!答案就出来了。

那么,规则3:即为上述的唤醒+交流+分析的所有思路,通知所有人。

总结

推理完毕,发现题目的难点在于由于有典狱长的存在,让任何“阴谋”无法实现,那么只能用“阳谋”。我就把我的策略告诉你,并且这个策略无法被针对,类似某些棋类游戏的先后手必胜策略。

来源

本题出自:掘金网@razertory用户在2018年于“每天一道算法题”专栏发的一个帖子。

转载于:https://www.cnblogs.com/maxstack/p/10949692.html

【原创分析帖】据说Google内部有史以来最难的一道面试题相关推荐

  1. Google内部流传的反多样性文章(10页完整版中文翻译)

    Google内部流传的反多样性文章(10页完整版中文翻译) 更新于8/5/17 7:25pm ET: Google 新上任的多样性和管理副主席 Danielle Brown 向谷歌员工发布了她最新的备 ...

  2. Google 内部的 Python 代码风格指南(译)

    微信搜索逆锋起笔关注后回复编程pdf 领取编程大佬们所推荐的 23 种编程资料! 来自:Why GitHub? 链接:https://github.com/shendeguize/GooglePyth ...

  3. Google内部 Python 代码风格指南(中文版)

    文末有干货 "Python高校",马上关注 真爱,请置顶或星标 这是一位大佬翻译的Google Python代码风格指南,很全面.可以作为公司的code review 标准,也可以 ...

  4. 快快快收藏!!Google内部Python代码风格指南(中文版)

    ????????关注后回复 "进群" ,拉你进程序员交流群???????? 来源丨菜鸟学Python 这是一位大佬翻译的Google Python代码风格指南,很全面.可以作为公司 ...

  5. [原创]分析某app直播地址的过程

    [原创]分析某app直播地址的过程 0x00 前言 自从疫情后,一直关注**电视台,直到前段时间再去看,没法播放了.最近空了,就去看看. 0x01 先抓包 有X-***-SIGNATURE的解密值 0 ...

  6. 锂电池二阶模型仿真 原创二阶RC模型, 内部参数自己拟合获得

    锂电池二阶模型仿真 原创二阶RC模型, 内部参数自己拟合获得, 具有与真实数据高阶拟合,已经攻克拟合难题 2RC等效电路模型特点: 1.可自己调节RC数量: 2.可输入实验数据模拟特定电池充放电特性. ...

  7. 从原理到实现丨手把手教你写一个线程池丨源码分析丨线程池内部组成及优化

    人人都能学会的线程池 手写完整版 1. 线程池的使用场景 2. 线程池的内部组成 3. 线程池优化 [项目实战]从原理到实现丨手把手教你写一个线程池丨源码分析丨线程池内部组成及优化 内容包括:C/C+ ...

  8. 用5why分析法分析一道面试题--------之Redis

    用5why分析法分析一道面试题--------之Redis 1 Redis 为什么快? 答:Redis属于纯内存方式缓存数据,相比mysql的存储模式,基本不涉及与磁盘IO所占用时间的问题 评论:首先 ...

  9. android多线程的本质,[原创]分析unidbg(unidbgMutil)多线程机制

    unidbg多线程分析 一. 概述 由于在工作中遇到了某翻译so中有多线程调用,因此使用unidbg分析(基于unidbgMutilThread)并增加阻塞唤醒机制(futex系统调用),但仍未调用成 ...

最新文章

  1. 用OpenCV和深度学习进行年龄识别
  2. Promise基础用法
  3. 先来先服务调度算法(FCFS)
  4. KEGG在线数据库使用攻略
  5. Java集合中HashMap日常问题及解决办法
  6. 10 个让你相见恨晚的 Python 骚操作
  7. 解决 【xshell 5 不能使用退格键和Delete建】的问题
  8. win7 下的 cmdhere 及其他
  9. 楼宇自控ba系统 服务器,楼宇自控BA系统
  10. Java学习--泛型
  11. win系统删除,已经注册的服务
  12. 经常用到的一些小病的预防的治疗
  13. 爬虫之requests库的使用
  14. 箭头函数写法_箭头函数
  15. Dxg——Raspberry Pi Pico python 开发笔记整理分类合集【所有的相关记录,都整理在此】
  16. 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题
  17. Excel怎么批量删除开头文本
  18. python实现乘法口诀表
  19. 电脑远程开机pcie卡
  20. intellij idea处理xml文件File encoding is disabled,Encoding is hard-coded in the text.提示的方法

热门文章

  1. HTML/CS3相关面试题目
  2. [转]屏幕保护色的设置
  3. SQLPLUS中的feedback设置
  4. 思岚轮式机器人底盘ZEUS怎么样?
  5. 轮履式农业机器人_轮履复合式农业机器人越避障控制研究
  6. 级数arctan(1/√n)
  7. dwg格式用什么打开
  8. opencv3.0 均值 标准差 函数 mean meanStdDev
  9. win10安装JDK1.8及配置java环境变量详解
  10. 一个集合了497个AI工具的人工智能网站