Google面试题-高楼扔鸡蛋问题

本文由 @lonelyrains 出品,转载请注明出处。 
文章链接: http://blog.csdn.net/lonelyrains/article/details/46428569

 

高楼扔鸡蛋问题   这个问题很有名了  早几年之前面试的时候都遇到过,但是当时也确实没搞清楚怎么做,后来也没管了。今天网上偶然碰到,打算趁这个机会彻底搞清楚,就写一篇博文吧。网上很多资料,但我感觉都不太易懂,每一步的推导是为什么。所以我这里只想写一种比较简单、比较完整的推演流程。

 

题目描述: (挑了一个比较严谨的描述。问题描述严谨很重要,不然会影响解题思路)
一幢 100 层的大楼,给你两个鸡蛋. 如果在第 n 层扔下鸡蛋,鸡蛋不碎,那么从前 n-1 层扔鸡蛋都不碎.
这两只鸡蛋一模一样,不碎的话可以扔无数次. 已知鸡蛋在0层扔不会碎.
提出一个策略, 要保证能测出鸡蛋恰好不会碎的楼层, 并使此策略在最坏情况下所扔次数最少.

 

问题分析:

 

1)最坏情况下所扔次数最少,比较绕口。想表达的意思是,在不明确知道哪一层会碎的情况下,要找到一种策略,通过最少的试验次数,得到临界楼层(恰好不会碎的楼层)。不明确知道,就需要考虑最糟糕的情况,而且这种策略与其他策略相比是最糟糕的情况下,最少的试验次数。

 

2)假设一种扔法:第一个鸡蛋,从50楼扔下去。如果碎了,第二个鸡蛋必须从1~49层逐层试验。如果第i层为临界层,且i≤49,这个时候,要试验的总次数是1 +(i - 1)。因为必须保证在没找到临界楼层之前,鸡蛋不能碎。如果没碎,则第一个鸡蛋可以接着从75层扔。因为即使这次碎了,还有个鸡蛋,可以继续逐层试验。对第一个鸡蛋的继续从中间分,就比较合理。

 

3)假设到代数:如果第一枚鸡蛋扔下去的层数为i,则碎了的情况,需要扔的总次数最糟糕的情况是1 + ( i - 1 );如果没碎,剩下的两个鸡蛋都在,需要扔的次数一定为1 + 用两枚鸡蛋来解决剩下的100 - i层的次数(这个问题跟原题是一样的,但是层数少了一些)。也就是 如果用f ( 100 )表示100层的最坏情况下的最少次数,那么从第i层扔鸡蛋的最糟糕的试验次数是 1+ Max( i - 1, f ( 100 - i ) ),Max表示这两者之间的最大值,是最最糟糕的情况了。  而 f ( 100 ) 就是对所有从1到100的所有i里, 1+ Max( i - 1, f ( 100 - i ) )的值最小的那个。

 

4)迭代公式: f ( 100 ) = Min ( 1 + Max ( i - 1, f (100 - i ) ) ) .   其中Max是针对的 i-1、 f ( 100 - i ) 两者 , 而Min是针对的所有的从1到100的i。

 

5)初始状态: 如果有一层,从第一层扔下去,不管碎不碎,最糟糕的情况也只需要判断一次。 即 f ( 1 ) = 1。而如题所述,第0层不会碎,则 不用扔也知道,即f(0) = 0。

 

6)最终结论:题目变成了分析一个迭代公式的值。翻译成了计算机语言,剩下的就可以交给计算机了。不需要知道怎么一步步算,这不应该是人干的事。只需要知道已经变成了可以循环递归的算式,可以交给计算机就行了。

// 实现代码   <a target=_blank href="http://blog.csdn.net/lonelyrains">blog.csdn.net/lonelyrains</a>
 
#include <stdio.h>
 
// #define MAX((a),(b)) (a)>(b)?(a):(b)  //注意这里也是常考的一点,应该写成下面的形式
#define MAX(a,b) ((a)>(b)?(a):(b))
 
int fun ( int layer )
{
    if ( layer <= 0 )
    {
        return 0;
    }
 
    if ( layer == 1 )
    {
        return 1;
    }
 
    int min = layer; // 一栋layer层的大楼试验次数肯定不可能超过layer次。
    int temp;
    for ( int i = 1; i <= layer; i++ )
    {
        temp = 1 + MAX(i-1, fun( layer - i ) );
        if( min > temp )
            min = temp;
    }
 
    return min;
}
 
int main()
{
    int layer = 19;
    printf("%d",fun(layer));
    return 0;
}
 

 

用上面的代码测试了一下,给layer赋值19,即针对一栋19层的大楼来算最坏情况的最少次数,就要很长时间才能出结果了(果然18层是地狱)....    
 

7)其他扩展:

① 问题的解法不止这一种描述,而且不一定要交给计算机算,因为这样递归算,计算机要累死了。可以优化到用很简单的数列求和公式得到。关于怎么来的,有两种思路。可以参考下面的第二个参考链接给出的基于意义的理解,这是一种思路,但是比较难理解。另外一种,就是纯粹的组合数学方法,将迭代公式转换成通项公式,这个问题还没找到有人这样写过,但是绝对可以有。

② 问题可以扩展为一栋n层的大楼,有m个鸡蛋;甚至不止一栋,而是p栋。 不管怎么样扩展,问题都可以归为找迭代公式。这个思路就是动态规划的精髓。

 

8)参考链接:

http://www.zhihu.com/question/19690210

http://blog.csdn.net/linj_m/article/details/9792821

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值