这题据说是 GOOGLE的面试题, 但是却真实的被一些软件公司拿来考应聘者. 比如我在前几年面试剑桥的博通公司/Broadcom, 在第二轮也被问到了这个问题.
题意是: 给你两个鸡蛋, 有个100层楼, 你可以把鸡蛋从任意一层楼扔下, 鸡蛋可能破, 也可能不破, 如果不破的话, 你可以继续用这个鸡蛋扔. 你需要用这两个鸡蛋来试出鸡蛋会破的最小楼层高度. 这两个鸡蛋一模一样. 问你采用什么策略可以使最坏情况下的尝试次数最少?
什么是最差情况? 如果你只有一个鸡蛋, 那么你最坏需要100次(需要从1层楼开始测试)才可以得到结论.
最直接的做法就是从第一层开始试, 然后第二层以此类推, 但是这种方法只需要用到1个鸡蛋即可. 如果第N层鸡蛋没碎但是第N+1层碎了, 答案就是N. 这种情况下最坏需要尝试100次.
如果我们在第50层扔呢? 如果鸡蛋碎了, 那么答案就在第1到第49层, 反之答案就在第51到第100. 鸡蛋碎了, 我们只有一个鸡蛋, 就只能从1试到49, 最坏情况下是 1 + 49次, 这种情况比上面最直接的做法(49)还差. 如果鸡蛋没碎, 那么我们还有两个鸡蛋, 但是层数只有50层了, 这时候就是一个子问题了.
同样, 再举个例子, 如果我们第一次在第33层, 鸡蛋碎了, 我们需要最坏情况下再试32次, 答案是32+1次. 如果鸡蛋不碎, 我们需要用两个鸡蛋试一下剩下的67层.
也就是说, 如果我们用 f(n) 来表示在第 n 层扔鸡蛋最差情况下的次数, 我们有两种可能, 再试 n – 1 次或者在剩下 n – i 层里用两个鸡蛋(子问题)的次数的最大值.
所以, 问题也就是找出所有情况下使 1 + max(i – 1, f(n – i)) 值最小的次数. 这里 1 就是因为你已经扔了一次了.
f(n) = min(1 + max(i – 1, f(n – i))) i 的范围从1到n
显然 f(1) = 1
用 C++ 来算算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // cached results; vector<int> cache(101, 0); int f(int n) { if (n == 1) { return 1; } if (cache[n] > 0) { // 已经计算出结果了. return cache[n]; } auto v = n + 1; for (auto i = n - 1; i >= 2; -- i) { v = min(v, 1 + max(i - 1, f(n - i))); } cache[n] = v; // 把中间结果保存起来, 避免重复计算. return v; } |
// cached results; vector<int> cache(101, 0); int f(int n) { if (n == 1) { return 1; } if (cache[n] > 0) { // 已经计算出结果了. return cache[n]; } auto v = n + 1; for (auto i = n - 1; i >= 2; -- i) { v = min(v, 1 + max(i - 1, f(n - i))); } cache[n] = v; // 把中间结果保存起来, 避免重复计算. return v; }
这里是把递归求解变成一个动态规化的最简单的方法, 就是缓存中间结果, 否则程序算不出结果. 以上求解得 14.
PS: 这题还有个升级版本(力扣887 Super Egg Drop), 需要结构二分搜索来解决.
英文: Google’s Two Egg’s Problem
面试经历
- 写了十几年代码, 谷歌/Google认为我还不够Senior
- Jane Street第一轮一小时面试体验卡(伦敦软件工程师)
- Meta/Facebook四次面试经历
- 三次冲击谷歌软件工程师: 我的面试起伏录 (谷歌面试是不是一生只有三次机会?)
- 记两次伦敦抖音面试经历(Tiktok)
- 我的面试谷哥GOOGLE伦敦SRE的经验和教训
- 记Facebook的第一轮技术面试(伦敦脸书)
- 记微软Principal SE的第一轮面试
- 我的AMAZON面试经历与经验之谈(亚麻伦敦面经)
- 离伦敦脸书最近的一次 - 记FACEBOOK伦敦终面经历
面试题
- 软件工程师面试: TCP/IP协议是什么?
- 软件工程师经典面试题: 当你在浏览器的地址栏敲入google.com并按回车后发生了什么?
- 谷歌面试题: 迷宫随机生成算法
- 软件工程师数据库面试技巧之 SQL中的第二名记录
- 软件工程师面试技巧之 动态规化 - 整数拆分
- 软件工程师面试技巧之 如何检查数独的有效性
- 去年 Google 的面试题 - 打印消息
- 软件工程师面试技巧之 使用哈希表降复杂度
- 微软面试题: 三角形的面积是多少?
- 英国 IT公司 电话面试的一些技巧 (程序员)
- C/C++ 中的内存管理器(堆与栈)
- C++的 map 当键(Key)不存在的时候会发生什么?
- 随机数独游戏的算法设计 (Sudoku)
- 经典二叉树的镜像的递归算法
- 谷歌的扔鸡蛋问题
- 面经: Python 的 List 和 Dictionary 有啥区别?
- 逻辑测试系列 - 一种只有4种语句的编程语言 - (1)
- 逻辑测试系列之二 - DECR
- 逻辑测试系列之三 - SUBT
面试技巧
面试其它
- 产品设计和系统设计面的区别(Product Design vs System Design)
- 45 分钟模拟面试(编程、系统设计)+职业发展建议
- 英国和美国IT公司面试的主要区别
- 拒了甲骨文(Oracle)的 Offer
loading...
上一篇: 编程练习题 - 如何合并两个有序的数组?
下一篇: C编程练习题: 判断整数是否有连续两个1
