【微软算法面试高频题】丢鸡蛋问题

本文探讨了如何使用动态规划解决经典的丢鸡蛋问题,旨在找出在有限的鸡蛋数量下,从一栋高楼中找到鸡蛋摔碎的最低楼层,以达到最小的测试次数。通过解析问题本质,介绍了不同策略,如线性扫描和二分查找,并详细解释了如何构建动态规划状态转移方程,优化枚举过程,最后给出了算法的时间复杂度和空间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 题目

如果你有2颗鸡蛋,和一栋100层高的楼,现在你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该如何用最少的测试次数对于任何答案楼层都能够使问题得到解决。

  • 如果你从某一层楼扔下鸡蛋,它没有碎,则这个鸡蛋你可以继续用
  • 如果这个鸡蛋摔碎了,则你可以用来测试的鸡蛋减少一个
  • 所有鸡蛋的质量相同(都会在同一楼层以上摔碎)
  • 对于一个鸡蛋,如果其在楼层iii扔下的时候摔碎了,对于任何不小于iii的楼层,这个鸡蛋都会被摔碎
  • 如果在楼层i扔下的时候没有摔碎,则对于任何不大于iii的楼层,这颗鸡蛋也不会摔碎
  • 从第1层扔下,鸡蛋不一定完好,从第36层扔下,鸡蛋也不一定会摔碎。
示例 1:
输入:k = 1, n = 2
输出:2
解释:鸡蛋从 1 楼掉落。如果它碎了,肯定能得出 f = 0 。 否则,鸡蛋从 2 楼掉落。如果它碎了,肯定能得出 f = 1 。 
如果它没碎,那么肯定能得出 f = 2 。 因此,在最坏的情况下我们需要移动 2 次以确定 f 是多少。 

示例 2:
输入:k = 2, n = 6
输出:3

示例 3:
输入:k = 3, n = 14
输出:4

2. 解析

实际上,我们的终极目的是要找出连续的两层楼i,i+1i,i+1ii+1在楼层iii鸡蛋没有摔碎,在楼层i+1i+1i+1鸡蛋碎了。问题的关键之处在于,测试之前,你并不知道鸡蛋会在哪一层摔碎,你需要找到的是一种测试方案,这种测试方案,无论鸡蛋会在哪层被摔碎,都至多只需要mmm次测试,在所有这些测试方案中,mmm的值最小。

对于只有1颗鸡蛋的情况,我们别无选择,采用线性扫描的方式。只能从1楼开始,逐层向上测试,直到第iii层鸡蛋摔碎为止,这时我们知道,会让鸡蛋摔碎的楼层就是iii(或者直到顶层,鸡蛋也没有被摔碎)。其他的测试方案均不可行,因为如果第1次测试是在任何i>1i>1i>1的楼层扔下鸡蛋,如果鸡蛋碎了,你就无法确定,i−1i-1i1层是否也会令鸡蛋摔碎。所以对于1颗鸡蛋而言,最坏的情况是使鸡蛋摔碎的楼层数i>=36i>=36i>=36,此时,我们需要测试每个楼层,总共36次,才能找到最终结果,所以1颗鸡蛋一定能解决36层楼问题的最少测试次数是36。

对于2个鸡蛋,36层楼的情况,你可能会考虑先在第18层扔一颗,如果这颗碎了,则你从第1层,到第17层,依次用第2颗鸡蛋测试,直到找出答案。如果第1颗鸡蛋没碎,则你依然可以用第1颗鸡蛋在27层进行测试,如果碎了,在第19~26层,用第2颗鸡蛋依次测试,如果没碎,则用第1颗鸡蛋在32层进行测试,如此进行(有点类似于二分查找)。这个解决方案的最坏情况出现在结果是第17/18层时,此时,你需要测试18次才能找到最终答案,所以该方案,解决36层楼问题的测试次数是18。相较于1颗鸡蛋解决36层楼问题,测试次数实现了减半。

还有种优化的方式是我们手中有两个鸡蛋,尝试使每个鸡蛋的测试任务大致相当,即给100开个平方根,第一个鸡蛋只测试整十楼层,第二个鸡蛋测试两个整十楼层之间的楼层。我们可以先测10楼,20楼,30楼···,直到第一个鸡蛋碎掉。如果我们测到30楼,第一个鸡蛋碎了,那我们就用第二个鸡蛋遍历测试21~29楼。这种策略最糟糕的情况会是99层是临界楼层,测试次数是10+9=19次。最好的情况是1楼是临界楼层,测试次数是1+2=3次。

实际上,如果不限制鸡蛋个数的话,二分思路显然可以得到最少尝试的次数,但问题是,现在给你了鸡蛋个数的限制 K,直接使用二分思路就不行了。

由于要制定一种泛化的策略,所以我们通过观察可以发现。第一颗鸡蛋的测试次数xxx,用来缩小范围;第二颗鸡蛋用来在小范围内查找临界楼层yyy;即x+y=nx+y=nx+

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值