zoukankan      html  css  js  c++  java
  • 扔鸡蛋问题

      腾讯面试的时候,面试官问了一道算法题,然后懵逼。。 遂记录于此。嗯,下面的题,有的是说鸡蛋,有的是说花瓶,但是实质都是一样的。 

      

    1、 一个100层的楼,扔下一个鸡蛋(花瓶),怎么判断在N层不碎,N + 1层碎,思路是什么?

      因为就一个鸡蛋,所以,我们很容易就可以想到从第一层开始扔就可以了,直到碎,说明这是N + 1层。 

    2、一个100层的楼,给你两个一模一样的鸡蛋(花瓶),判断这个鸡蛋的硬度,即N层不碎,N + 1层碎,最少需要多少次? 

    方法一:遍历

      这里当然也可以按照第一个问题的方法来实现,即从第一层开始向上,直到摔碎为止,但是这种方法显然是低效的。

    方法二二分查找

      当时就想到了使用这种方法,即采用二分查找的思路,第一次在50层扔:如果碎了,那么从第一层开始向上扔(因为就剩下这一个了,不能取中间值了)....; 如果没有碎,就在75层扔.....。 这样貌似速度快了不少,但是如果这个瓶子恰好是49层碎呢,那么就是在50层扔碎了一次,然后从第一层开始又扔了49次,一共花费了50次,这样的结果还不过第一种方法:即开始就从第一层扔,这样最后才49层。

      所以,这种方法也是不可取的。 

    方法三动态规划

       其实,对于这个问题,我们可以将之转化为: 如果给定2个鸡蛋,n次抛鸡蛋实验,在最坏的情况下,可以保证测出多少层

      在这个问题中,我们需要注意的时可以保证测出多少层。 为了保证能够在有限的n次测试中测出需要的层数,我们需要首先考虑最坏的情况,也就是第一次抛鸡蛋蛋就碎了的情况;如果第一次就碎了,那么我们为了测出楼层就只能从底层开始一层层往上抛了(因为如果不是这样,比如我从碎了的下一层开始抛,那么如果鸡蛋也碎了,就说不清了)。

      这样,我们就确定了每次试验鸡蛋的起抛位置,那就是n层,因为在n层抛,即使碎掉了也可以保证在剩下的n - 1次试验当中,让鸡蛋覆盖这所有的n层楼,如果高于n这个数字就不可能了。

      那么,如果我们的第一次鸡蛋没有碎呢? 那么这个问题就很自然的转化为了:在最多n - 1次抛鸡蛋的试验中,可以保证测出多少层。 可以看出,这是一个典型的动态规划的问题。

      

    • 抛1次; 只能测出一层,毫无疑问。
    • 抛2次: 从2楼起抛,如果碎了,在1楼抛;没碎,转化成一个2个鸡蛋抛一次的问题(上面这个问题),所以抛两次可以测出2 + 1 = 3层。
    • 抛3次: 从3楼起抛,如果碎了,从1楼开始向上抛; 没碎,转化为一个2个鸡蛋抛两次的问题(上面这问题),所以抛3次可以测出3 + 3 = 6层。
    • 抛4次: 从4楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛三次的问题(上面这问题),所以抛4次可以测出4 + 6 = 10层。
    • 抛5次: 从5楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛4次的问题(上面这问题),所以抛5次可以测出5 + 10 = 15层。 
    • 抛6次: 从6楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛5次的问题(上面这问题),所以抛6次可以测出6 + 15 = 21层。
    • 抛7次: 从7楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛6次的问题(上面这问题),所以抛7次可以测出7 + 21 = 28层。
    • 抛8次: 从8楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛7次的问题(上面这问题),所以抛8次可以测出8 + 28 = 36层。
    • 抛9次: 从9楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛8次的问题(上面这问题),所以抛9次可以测出9 + 36 = 45层。
    • 抛10次: 从10楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛9次的问题(上面这问题),所以抛10次可以测出10 + 45 = 55层。
    • 抛11次: 从11楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛10次的问题(上面这问题),所以抛11次可以测出11 + 55 = 66层。
    • 抛12次: 从12楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛11次的问题(上面这问题),所以抛12次可以测出12 + 66 = 78层。
    • 抛13次: 从13楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛12次的问题(上面这问题),所以抛13次可以测出13 + 78 = 91层。
    • 抛14次: 从14楼起抛,如果碎了,从1楼开始向上抛;没碎,转化为一个2个鸡蛋抛13次的问题(上面这问题),所以抛14次可以测出14 + 91 = 105层。
    • 。。。
    • 。。。

      从上面的推断中,就已经可以看出14次,就可以测出105层了,所以100层也需要14次就可以测出来。

    注意:

      可能有些同学即使大概理解,但是还不是能说清楚是否是最好情况还是最坏情况,那么我们只需要拿出其中一个例子来举例说明就可以了。 比如 2个鸡蛋抛3次能否测出一个6层高楼的临街位置,我们可以这么思考: 3次机会,我们第一次从3楼开始抛,如果碎了,那么剩下2个鸡蛋,2次机会一定可以找到临界位置,或者没有临界位置(即1层楼就会摔碎的情况); 如果3楼没有摔碎,那么就是说4/5/6三楼还有2个鸡蛋,两次机会,而实际上4/5/6可以看做1/2/3,那么我们就拿2个鸡蛋2次机会开始,第一次从2楼抛,如果碎了,那么还有一个鸡蛋一次机会一定可以可以找到的;如果没有碎,那么还有2个鸡蛋一次机会,也就可以测试3层是否会碎。所以,通过分析,2个鸡蛋抛3次可以测出一个6层楼高的临界位置,那么同样,2个鸡蛋14次机会也可以测出105层楼高的临界位置,那么100层也一定是可以的了。

    参考文章:记两道ebay面试题

  • 相关阅读:
    Maven入门指南12:将项目发布到私服
    Groovy学习:第四章 Groovy特性深入
    jQuery部分疑问及小结
    Windows自动化---模拟鼠标键盘
    适配器
    object都有string
    spinner
    context
    OnclickListener
    学习-----领进门,看个人
  • 原文地址:https://www.cnblogs.com/zhuzhenwei918/p/7209026.html
Copyright © 2011-2022 走看看