1. 问题描述

有一批芯片(n片),里面有好芯片有坏芯片,我们不知道哪片是好的哪片是坏的,只知道里面的好芯片一定比坏芯片至少多出一片
现在有一个检测设备,同时将两片芯片放进去,它们会各自报告对方的情况,好芯片的报告结果一定是真实的,坏芯片的报告结果是不确定的(有可能是真实的,也有可能是假的)。会有这样的报告结果:

芯片A的报告 芯片B的报告 结论
AB都好或者都坏
假如两个都是好的,显然矛盾了,因此至少有一个坏的
同上,至少有一个坏的
反证,可得至少一个是坏的

现在要求从这批芯片中挑出一个好的芯片。
从这批芯片当中随便挑出一个芯片,用剩下的芯片挨个去和它进行检测。
当n为偶数时:

待测试芯片 其余芯片(奇数个)
好芯片 剩余芯片中好芯片的个数仍然会比坏芯片至少多一片,因此将会有超过一半的芯片报告是好芯片
坏芯片 同上,有超过一半的芯片报告是坏芯片

当n为奇数时

待测试芯片 其余芯片(偶数个)
好芯片 剩余芯片中好芯片的个数不会比坏芯片少,因此将会有至少一半的芯片报告是好芯片
坏芯片 剩余芯片中好芯片的个数比坏芯片多至少两片,因此将有超过一半的芯片报告是坏芯片

推论1: 从n个芯片中随便挑出一个,如果是好芯片,则至少有一半的芯片报告为“好”;
逆否命题:如果报告结果为好的少于一半,那么这一定不是一个好芯片(那就是坏芯片了)。
推理2: 从n个芯片中随便挑出一个,如果是坏芯片,则应有超过一半的芯片报告为“坏”;
逆否命题:如果报告结果为坏的芯片至多一半,那么这肯定不是坏芯片(那就是好芯片了)。

2. 常规法

  1. 芯片总数为偶数(2k):
    挑出一个芯片X(待检芯片)后,剩下(陪检芯片)奇数个(2k-1),在这2k-1个中,好的肯定比坏的多。检测报告(只看陪检芯片的报告)有如下两种情况:
陪检芯片报告 结果分析
报好多于报坏 X肯定是好芯片。因为如果A是坏芯片,又发布报告的芯片中好芯片多,那么结果中报坏的肯定要多于报好的。
报坏多于报好 X肯定是坏芯片。原因同上,因为发布报告的芯片中好芯片占有优势。
  1. 芯片总数为奇数(2k+1):
    挑出一个芯片X后,剩下奇数个(2k),在这2k个中,好的至少也占了半数。检测报告有如下三种种情况:
陪检报告 结果分析
好坏各占一半 根据推理2的逆否命题,这肯定不是坏芯片,那X就是好芯片了。或者我们来反证一下,假如是坏芯片,那么剩余的2k个芯片中好的就不只半数了,至少也比坏的多两个,否则与大前提(在一批芯片中好的至少比坏的多1个)矛盾。这样的话,报告里报坏的就不止一半了,而是多于一半,这与我们看到的报告不相吻合,因此X一定是好芯片。
好多于坏 因为陪检芯片中至少有一半好芯片,所以如果是坏芯片,那么报坏的芯片数不可能比少于一半。因此这是好芯片
坏多于好 同上,这是坏芯片

以上我们从各种情况分析得出了当面对这一堆芯片的分析报告时,我们如何去判断这是什么样的芯片。
现在再来解决这个问题,算法很简单:挑出一个芯片X,用剩余的检测它,然后看它是否是好芯片,如果是则完成问题,如果不是则再换一个进行检测,直到我们挑出一个好的为止。
算法分析:每次挑选需要O(n)次检测,运气好的话第一次就挑中了一个好的,运气不好最多只需要n/2次(上取整)。平均的话需要两次。

3. 分治法

我们能想到的做法是,先两两一组进行检测,如果两个报告都是好(这两个芯片同好或同坏),则将这两个芯片任意留下一片,否则就将这两个芯片都舍弃。然后按同样的做法对剩下的进行下一轮的检测。
能否行的通?分治法的关键在于子问题和原问题应该有相同的性质。也就是说,经过一轮检测,剩下的芯片中仍然应该保持着好的至少比坏的多一个这条性质
证明:

  1. 假如芯片数为偶数

    • 设在决定任留一个的芯片对中同为好的有2k个(任留其中一个),同为坏的有2j个(任留一个),舍弃的芯片中,好的m个坏的n个(因为在上面的分析中可以看到,舍弃的情况中都是坏的至少一个,也就是说n >= m)。
    • 根据题设有,2k + m > 2j + n。
    • 综合上面的可知,2k > 2j,即k > j,也就是说剩下来的芯片中,好的仍然比坏的多。
  2. 假如芯片数为奇数
    • 设在决定任留一个的芯片对中同为好的有2k个(任留其中一个),同为坏的有2j个(任留一个),舍弃的芯片中,好的m个坏的n个(因为在上面的分析中可以看到,舍弃的情况中都是坏的至少一个,也就是说n >= m),还有一个没有参加检测的。
    • 根据题设有,2k + m >= 2j + n,注意这里取等号了,因为剩下的那个有可能是好的。
    • 综合上面的可知,k >= j,也就是说剩下来的芯片中,好的不能保证比坏的多了。
    • 这个时候就应该对剩余的那个进行一次检测了,用留下的芯片对其进行一次检测,因为剩下的芯片中好的至少还是占了一半,因此如果报告中好的报告占一半或以上,那么这个就是好芯片,将其留下,那么我们就直接完成了这个问题,找到一个好芯片。否则直接将它丢掉。因为我们已经知道了未参加检测的那个是坏芯片,这时我们再来看第2条,会发现2k + m >= 2j + n + 2,那么显然k > j成立,保持了原来的好的至少比坏的多一个的性质。

算法分析:分治法的时间复杂度递推方程为W(n) = W(n/2) + n/2,n/2是两两分组需要进行的检测次数,在出现有奇数个芯片的时候,有一个剩下的,需要额外进行最多n/2次(因为2k + 2j < 芯片总数,那么k+j 一定小于总数的一半)检测,但是却有一半的几率使递归提前终止(剩下的那个是好的)。最终的综合检测次数为O(n)。

4. 总结

总的来看,分治法稍稍好一些。但是其实常规法也不错,因为我们知道,前3次都没挑到好芯片的概率小于12.5%,前四次都没挑到的概率小于7.5%,…,前7次都没条中的概率小于1/128=0.78%,已经不足1%了,基本上我们可以假定只需要不超过7次就可以挑到一个好芯片。因此其实常规法的效率也不错,而且因为不需要递归,节省了空间。但是常规法需要大量的分析。花了一下午分析写这个东西,打乒乓球去了。

芯片检测(分治法经典问题)相关推荐

  1. C语言--分治法经典例题--循环日程安排问题

    问题描述: 有size=2^n个选手要进行网球循环赛,设计一个满足以下要求的比赛日程表.满足每个选手必须和其他n-1个选手各赛一次.每个选手每一天只能赛一次.循环赛在n-1天内结束. 解法: 这个图标 ...

  2. 分治法的关键特征_经典算法思想2——分治(Divide-and-Conquer)

    分治法,字面意思是"分而治之",就是把一个复杂的1问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解,原问题的解即子问题的解的合并,这 ...

  3. 分治法的经典问题——大整数相乘

    分治法的经典问题--大整数相乘 分治法的原理 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解.即一种分目标 ...

  4. 分治法的思想与经典题目

    目录 分治法简介 分治法主定理 分治算法的时间复杂度 分治法的基本步骤 分治法的使用条件 分治法的经典题目 50. Pow(x, n) 53. 最大子序和 169. 多数元素 分治法简介 分治法,即& ...

  5. 分治法的计算时间、时间复杂度推导以及经典算法分析

    分治是一种解决复杂问题的思想,它可以将一个问题划分成多个小的问题,通过合并这些问题求得原问题的解.本文对分治法进行复杂性分析,并通过这种方法分析几个具体算法的时间复杂度. 文章目录 1 分治法的复杂性 ...

  6. 棋盘覆盖-经典的分治法问题

    棋盘覆盖-经典的分治法问题 一.问题概述 二.适用方法 三.代码展示 四.运行结果 五.算法分析 一.问题概述 在一个 2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格, ...

  7. 四种解法——求子序列的最大连续子序和(普通解法、求和解法、分治法、O(n)级解法)(面试经典题)

    励志用少的代码做高效表达 在这四种解法里,解法一是通法,可以学到规律和知识,做基础之用:解法二在解法一的基础上做改进,锻炼思维:解法三则是大名鼎鼎的分治法,涉及到递归的知识,算是"高效算法设 ...

  8. LeetCode 23. Merge k Sorted Lists--Python解法--优先队列,分治法

    题目地址:Merge k Sorted Lists - LeetCode Merge k sorted linked lists and return it as one sorted list. A ...

  9. 005-算法-分治法

    一.概念: 在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范式.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以 ...

最新文章

  1. Linux编译器GCC的使用
  2. POJ 2828 Buy Tickets | 线段树的喵用
  3. MFC多线程同步互斥
  4. error C4335: Mac file format detected: please convert the source file to either DOS or UNIX format
  5. muduo网络库学习(七)用于创建服务器的类TcpServer
  6. JAVA开发环境及其开发
  7. 如何节约数据中心空间
  8. web获取多行mysql结果_mysql中的多行查询结果合并成一个
  9. 女子驾驶蔚来汽车被迫停留长安街超1小时 官方回应:司机连续误操作
  10. elk-可视化图标(nginx)
  11. Pandas DataFrame 函数应用和映射
  12. 数字图像取证:初学者手册
  13. 如何使用JavaScript重定向到另一个网页
  14. mybatis order by concat用法
  15. android 定位 指南针,Android 实现指南针效果
  16. 剑指offer 二叉搜索树与双向链表
  17. 面试 | 3.5 万字总结 Java 后台研发常见面试题
  18. 关于二分查找那些事儿~~~~看完至少节省你两个半月的时间!!!!!
  19. SequoiaDB 巨杉数据库应用场景
  20. 毕业设计/论文答辩演讲稿通用模板

热门文章

  1. 2023跨年代码(烟花+自定义文字+背景音乐+雪花+倒计时)
  2. 瑞幸咖啡的最终目标并不是做国内市场大哥
  3. 商店销售某一商品,每天公布统一的折扣(discount)。同时允许销售人员在销售时灵活掌握售价(price),在此基础上,一次购10件以上者,还可以享受9.8折优惠。现已知当天3个销货员的销售情况为
  4. 各种抠图动态图片_10种ps抠图办法(动态图演示全过程)
  5. 写一个将华氏温度转换成摄氏温度的程序,转换的公式是:°F = (9/5)*°C + 32 其中C表示摄氏温度F表示华氏温度程序的输入是一个整数表示华氏温度。输出对应的摄氏温度也是一个整数(java)
  6. android的contentResolver,contentProvider简介(附带个获取手机联系人及头像实例)
  7. 小强说话---子曾经曰过的
  8. 大数据应用场景全景图
  9. 反对称矩阵乘任意矩阵满足交换性?
  10. 谁不喜欢《长安十二时辰》? | Alfred数据室