小白鼠喝毒水的问题。

  有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡,至少要多少只小白鼠才能在24小时时鉴别出哪瓶水有毒?

这是一道很经典的面试题目,先说解题方法吧,2^n >= 1000,其中n就是小白鼠的数量。如果知道答案了,也许很多人就恍然大雾,当然有些专业的人士用下面的归纳法证明了下:

1)当n=1时,即有2瓶水,任取一瓶水喂老鼠,若24小时后老鼠死,则此瓶水有毒;若24小时后老鼠没死,则此瓶水无毒,另一瓶水有毒。课件只需一个老鼠即可判断出哪瓶有毒。即当n=1时命题成立。

2)假设当n=k(k>1)时,命题为真。即须k只老鼠即可判断出哪瓶水有毒。
   则当n=k+1时,即有2^(n+1)瓶水。
   将水分成2组,命名为P1和P2,每组2^n瓶水.
   则这两组瓶中有一组全没毒,另一组中有仅一瓶有毒。
   a) 取1只老鼠、任取一组瓶子,假设为P1,将P1中的全部瓶子水都让老鼠尝一下。则24小时后可以根据此老鼠的生死情况判断毒药在哪一组。
   b) 取k只老鼠,根据假设可知当n=k时,可判断哪瓶水有毒。用这k只老鼠同时去检测P1和P2,则24小时后可挑出P1中的某一瓶和P2中的某一瓶,这两瓶可能有毒。
   根据a、b中的结果综合分析,可得知毒药瓶是哪一个。
   即当n=k+1时,命题为真。

命题得证。


这个证明应该是没问题,但是我很感兴趣的就是,如何猜出来这个命题的哪?我就说下这个过程吧,来检测瓶中的水有没有毒,只能靠小白鼠死没死亡来判断,也就是2种状态,这里1表示死亡,0表示存活。那么10个小白鼠,那么可以表示2^10(代表10次方)中状态,也就是1024。那么这1024种状态能不能对应出那瓶水有毒那,如果可以这个题目就解决了。看到这里,又回到了上面的证明,这个归纳法明显可以证明,此猜想没问题。由此归纳法可以看出,此问题符合算法中的,动态规划法,也就是该问题可以分解成更小的问题,1000(也就是1024瓶以内)瓶水给10个老鼠喝,512(512瓶水以内)瓶水给9个老鼠喝...以此类推,平且每个大问题的子问题,还跟这个大问题有关系,由数学归纳法证明的第二步,可以看出,通过子问题的解决,更大的问题带入到步骤2中就可以解决了。

以上步骤说了半天都是,说明此方法是正确的,可证明的。但是如果要问怎么安排老鼠喝水,才能判断那瓶有毒那?也就是把这个动态规划的算法如何来实现。其实改归纳法证明中的第二步骤中的b)后面的内容,已经透露出了运用的实现方法。也就是把有所有的水给某一个老鼠P10喝,剩下的老鼠喝的水都不能包含P10喝的那瓶毒水,那么如果P10死亡了,剩下的都活着,就检查出来毒水了。以此类推老鼠P9喝的水肯定包含一瓶其他老鼠都没喝过的,这样才能检查出这瓶水有毒。这样我们就可以得出下面的结论:

1 表示死亡 0 表示存活

0000000001       P1喝了第一瓶的水,其他老鼠都没喝,那么P1老鼠死亡,其他没死推断出第1瓶水有毒

0000000010       P2喝了第二瓶的水,其他老鼠都没喝,那么P2老鼠死亡,其他没死推断出第2瓶水有毒

0000000100       P3喝了第4(2^2)瓶的水,其他老鼠都没喝,那么P3老鼠死亡,其他没死推断出第4(2^2)瓶水有毒

......

这里开始有疑问了,那么从第2---第4瓶水,中间的那瓶水有毒如何推断那?这里就用到一个方法叫组合。11代表第3瓶水有毒,也就是P1和P2必须同时喝第三瓶水,而P3不能喝,那么P1和P2死,P3没死就可以得出第三瓶水有毒。下面的各瓶水的判断,都快可以依据这个理论类推,根据上面数学归纳的证明,应该可以判断出来所有的剩余的水。这里可以发现一个显而易见的规律,P1老鼠所有奇数位置的水都得喝,因为P1老鼠可以测试有毒瓶子的位置为xxxxxxxxx1 (x代表未知),换成10进制必须包含一个2^0也就是1,那显然是奇数。只有这样才能组合出水的位置,从刚才第三瓶水的判断也可以看出。P2老鼠喝水当然也有规律了,xxxxxxxx1x,换成10进制必须包含2^1也就是2,根据2进制转换成10进制的算法,我们看下面的数字4=2^2 , 3=2^1 + 2 ^ 1 , 2 = 2^1 , 1=2^0其中3就包含了2^1方,也就是3号瓶子的水,P2必须喝,根据这个方法5=2^2 + 2^0那么5号p2就不用喝,我们总结下就可以看出,其实P2如果换成10进制的话,每隔2个位置就需要P2喝,也就是6,8,10,12...都需要。那么P3那同理根据这个推算方式,每隔4个位置就需要P3喝,也就是4,8,12...。至此所有的老鼠应该喝的水所在的瓶子的位置都判断出来了。

上面的方法,讲完后,如果你学习过计算机网络中海明码的编码规则,那你岂不是就恍然大悟了。这不就是海明码的编码规则么?下面我们就对比下海明码的编码规则:


下面看如何计算海明码(Hamming Code )

海明码(Hamming Code )编码的关键是使用多余的奇偶校验位来识别一位错误。

码字(Code Word) 按如下方法构建:

1、把所有2的幂次方的数据位标记为奇偶校验位(编号为1, 2, 4, 8, 16, 32, 64等的位置)

2、其他数据位用于待编码数据. (编号为3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17等的位置)

3、每个奇偶校验位的值代表了代码字中部分数据位的奇偶性,其所在位置决定了要校验和跳过的比特位顺序。

位置1:校验1位,跳过1位,校验1位,跳过1(1,3,5,7,9,11,13,15,…)   这里和老鼠和水的位置是不是一样的

位置2:校验2位,跳过2位,校验2位,跳过2 (2,3,6,7,10,11,14,15,…)

位置4:校验4位,跳过4位,校验4位,跳过4(4,5,6,7,12,13,14,15,20,21,22,23,…)

位置8:校验8位,跳过8位,校验8位,跳过8(8-15,24-31,40-47,…)

如果全部校验的位置中有奇数个1,把该奇偶校验位置为1;如果全部校验的位置中有偶数个1,把该奇偶校验位置为0.

举例说明:

一个字节的数据:10011010

构造数据字(Data Word),对应的校验位留空_ _ 1 _ 0 0 1 _ 1 0 1 0

计算每个校验位的奇偶性 ( ?代表要设置的比特位):

位置1检查1,3,5,7,9,11:

? _ 1 _ 0 0 1 _ 1 0 1 0. 偶数个1,因此位置1设为0,即: 0 _ 1 _ 0 0 1 _ 1 0 1 0

位置2检查2,3,6,7,10,11:

0 ? 1 _ 0 0 1 _ 1 0 1 0. 奇数个1,因此位置2设为1,即: 0 1 1 _ 0 0 1 _ 1 0 1 0

位置4检查4,5,6,7,12:

0 1 1 ? 0 0 1 _ 1 0 1 0奇数个1,因此位置4设为1,即: 0 1 1 1 0 0 1 _ 1 0 1 0

位置8检查8,9,10,11,12:

0 1 1 1 0 0 1 ? 1 0 1 0偶数个1,因此位置8设为0,即: 0 1 1 1 0 0 1 0 1 0 1 0

 

因此码字为: 011100101010.

 查找并纠错一位错误

上例中构建了一个码字 011100101010,假定实际接收到的数据是011100101110. 则接收方可以计算出哪一位出错并对其进行更正。方法就是验证每一个校验位。记下所有出错的校验位,可以发现校验位28的数据不正确错误校验位 2 + 8 = 10, 则位置10的数据出错。一般说来,对所有校验位进行检查将所有出错的校验位置相加得到的就是错误信息所在的位置.

至此终于发现原来这个面试题目,使我们学过的。是不是感觉自己学的东西太糙了么?

  • 8
    点赞
  • 6
    收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 4

打赏作者

animeng

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值