谈谈100层会碎的两颗玻璃球

问题

有这样一道经典面试题(据说曾被纳入谷歌校园招聘题库),大意为有一栋100层高的大楼,已知从某一层起,玻璃球下落一定会碎,现给你两颗这样的玻璃球,如何用最少的试验次数,确定玻璃球在哪层刚好会碎。

 

笔者曾在算法工程师笔试阶段遇到这一问题时,不假思索地认定这是考察对时间复杂度的理解,内心暗鄙这有何难,一时喜上眉梢,大笔一挥,写下了二分法查找的答案。

      

转念一想,不对啊,第一次放在50层试,如果碎了,第二次放25层再丢,也碎了,还没找到临界层,“球球”没了可咋整?(???)当即就将已经写好的答案叉掉,因为我已清楚地知道,二分法查找于此处只是个温柔的陷阱…

      

那这道题究竟该作何解?一层一层往上加着试,肯定是找得到的。这样的做法对应遍历查找,时间复杂度O(n),在此场景下最坏情况对应99次(因为已知100层一定碎)…可未免过于简单粗暴,仔细想想用一颗球也就够了,更加与“用最少试验次数”的要求相背离。

      

出题人给了你两颗肯定有他的道理,如何利用好两颗球呢?不妨换一个思路,其中一颗粗略确定范围,另一颗精确锁定临界层(可以参考高中物理课上接触到的螺旋测微器,有粗调和微调的分工合作)。有道是:碎掉一颗也不愁,还有备用玻璃球。

      

第一颗(后文称“球一”)用来做炮灰,假定每多少层丢下(粗调),如果碎掉,第二颗球(后文称“球二”)在碎掉前一次丢球的层数和碎掉的层数之间再逐一尝试(微调)。现在的问题变成了如何确定丢球的层数间隔。对算法有一定了解的伙伴都知道,时间复杂度的求解考虑的是最坏的情况,假设间隔层数为x找出临界层所需的至多试验次数f(x)的表达式为:

     

ceil表示天花板除,向上取整(例ceil(5.5)=6; ceil(5)=5)。求 x+c/x (x为自变量,c是常数)的最小值相信大家都不陌生,当x = c/x = √c 时,有最小值2√c。除求导可证外,这里讲另外一种证明。已知x和常数c均为正值,有:

      

故此处(c=100),x=10即每十层丢球一,可使方案为每固定层数做范围尝试之下最优,至多的试验次数为18次(球一10, 20…90层9次,球二试91-99层9次)。

      

问题至此似乎已被解决,甚至还有简明易懂且严谨的数学证明,但…我们忽略了一个问题,那就是概率或者叫运气,对于结果的影响。整个问题的精髓,也就在这里。

      

机智如你可能已经看出来了,上述的结果是不确定的,试验总次数在2-18波动,而最坏的情况也会随着临界层的变大而增加试验次数(临界层在1-10层至多只需试验10次,而在90-100层则可能需18次)。当丢球一的间隔层数x增大时,会让球二定位临界层的次数增加,但球一测大段范围的次数相应减少。能不能找到一种动态的间隔层数,使最终的试验次数达到一种平衡,平衡的直接体现就是临界层无论在哪一段,最坏情况下的试验次数相等通过如下简图可以看出,总次数 = 球一尝试次数+球二精准定位次数,而球一每向上走一段,若想保证总次数相同,则需球二少定位一次,即每一段包含层数递减一层!那么有:

      

      

计算得:x ≥ 14,所以采用该方案球一第一次放到14层丢下来,第二次放到第27层(14+13)丢下来,以此类推,可以保证最多14次就可以试出哪一层刚好丢下来会碎。该方案小于上一方案平均分段产生的最坏情况18次!

      

层高100和仅有两颗球限制条件下的确定临界层高问题,至此就告一段落了,其实只要稍稍修改一下条件(譬如给你三个球或更多),就可以衍生出许多变式问题,在此就不展开详细讨论了。鉴于本文是笔者的公众号处女作,难免有许多不成熟的地方,欢迎广大读者批评指正(指正可以,批评不接受,就酱)。

      

写在最后

笔者是材料工程&材料化学背景出身,你要是想跟我讨论为啥玻璃球99层没碎而100层碎了,我或许会从选材或者材料强度的维度说说对问题的理解,说不定还能给你一些建议让球球回个炉变得100层下落也不碎。材料陈冠希,童叟亦无欺;转行大数据,你上你也行。下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值