Problem of Two Eggs
在知乎上看到这么一道题, 原题描述的不太严谨, 其大意是:
一幢 200 层的大楼, 给你两个鸡蛋. 如果在第 n 层扔下鸡蛋, 鸡蛋不碎, 那么从前 n-1 层扔鸡蛋都不碎. 这两只鸡蛋一模一样, 不碎的话可以扔无数次. 已知鸡蛋在 0 层扔不会碎.
提出一个策略, 要保证能测出鸡蛋恰好会碎的楼层, 并使此策略在最坏情况下所扔次数最少.
一看, 答案里票数多的都是扯淡的, 正解都没给详细说明所以被压下去了.
面试 Hulu 的最后一轮, 是我现在的 manager zhibing 来面试, 他只问了我这一个问题. 不过把 200 层换成了 100 层, 把鸡蛋换成了瓶子 (瓶子更科学!).
首先搞清楚这题的意思:
第一个瓶子用来试探, 只要它从
面试时我得到的题目描述也不太严谨, 没有说 "最坏情况下代价最小", 因此我愚昧了一会才明白这题的意思.
"最坏情况下代价最小" 这句话十分重要, 它已经反映了题目的数学结构:
我们如果把任何一种策略看成一个决策树,
每一次扔瓶子都会有两个子节点, 对应碎与不碎的情况下下一步应该扔的楼层.
那么, 策略的一次执行, 是树中的一条从根往下走的路,
当且仅当这条路上出现过形如
再看一个节点处, 选择楼层时会发生什么. 容易看出, 选择的楼层如果变高, 那么 "碎子树" 高度不减, "不碎子树" 高度不增. 同样的, 选择的楼层变矮的话, "碎子树" 高度不增, "不碎子树" 高度不减.
这时候答案很明显了: 为了使两子树中高度最大者尽量小, 我们的选择应当使两子树高度尽量接近. 最终希望的结果是, 整个二叉树尽量像一个满二叉树.
假设第一次在根节点上, 我们选择扔
也即, 如果第一次扔在
所以第一次扔 14 层, 最坏需要 14 次 (策略不唯一, 树的叶子可以交换位置).
200 层的话,
面试的时候脑子有点乱, 没想到树, 就只是从两边要平均的角度来算的, 所以有点不自信. 最后算出来 14 之后由于是个近似 (其实上取整就对了), 又试了一下 15 和 13. 之后在重新理思路, 这时候貌似已经过了很久, zhibing 就问怎么样了, 我说了下答案, 然后说我没有想出很好的办法证明 14 一定是最优的. zhibing 就直接说: 这是对的, 应该是一个等差数列. 然后下一句话就是别的什么了...
所以面试要多说话啊....................!
以上说的是数学做法.. 代码做法就简单的多, 看面试是要答案还是要程序了.
设
以下代码 python3 only:
|