摔玻璃球(鸡蛋)查找临界楼层

1. 问题介绍

已知有一栋 F F F层的大楼和 N N N个完全相同的玻璃球(鸡蛋),存在临界楼层 F c F_c Fc,从 F c F_c Fc层或比它高的楼层落下的玻璃球都会摔碎,从比 F c F_c Fc低的楼层落下的玻璃球都不会摔碎,要求用这 N N N个玻璃球确定 F c F_c Fc的值,请给出最优策略。

摔玻璃球(鸡蛋)查找临界楼层问题是谷歌的一道经典面试题。CSDN、LeetCode以及知乎上讲解该问题的文章不少,但是都讲得不全面不透彻,本文将全面考虑玻璃球个数和楼层数为任意正整数的解法。

2. 问题分析

首先要明确何为最优策略,最优策略是指用最经济的办法找出临界楼层,具体包括两个条件:1.查找次数最小,2.在满足条件1的前提下摔碎球数最小

目前玻璃球数和楼层数已知,临界楼层未知,也就是说任意一层都是潜在的临界楼层,那么使用某种策略所需查找次数及摔碎球数可能会因临界楼层的不同而不同。

假设每层楼为临界楼层的概率是均匀分布的,那么查找次数的期望为临界楼层的所有可能取值对应的查找次数的平均值(以下简称为平均查找次数),摔碎球数的期望为临界楼层的所有可能取值对应的摔碎球数的平均值(以下简称为平均摔碎球数)。

某种策略的平均查找次数越小,该策略在实际应用中获胜的概率就越大;若出现平均查找次数相等的情况,则平均摔碎球数越小,获胜的概率就越大

当然,获胜概率大并不能保证必胜,最终谁能获胜要看临界楼层到底是哪一层,也就是说要碰运气。

要使平均查找次数最小,首先想到的就是二分查找:用一个玻璃球在中间楼层查找,若玻璃球摔碎,则用下一个玻璃球查找该层下方楼层,若玻璃球没碎,则继续查找该层上方楼层。但二分查找真的适用于临界楼层查找问题吗?临界楼层查找与二分查找有什么区别和联系呢?

临界楼层查找二分查找区别与联系:

区别:二分查找的关键字可以无限次使用,而临界楼层查找设定了真实场景,查找所用的玻璃球是消耗品且数量有限

联系:二分查找有关键字在序列中和不在序列中2种情况。当关键字在序列中时,关键字与序列元素的关系有大于、等于、小于3种,其中“等于”是临界点,当关键字等于序列元素时查找成功;当关键字不在序列中时,关键字与序列元素的关系只剩大于和小于2种,序列元素中小于关键字的最大值以及与其相邻的大于关键字的最小值都是临界点,当关键字与二者都比较过后,才能确定查找失败。而临界楼层查找实际上就是二分查找关键字不在序列中的情况。玻璃球与每个楼层的关系只有能摔碎和不能摔碎2种,其中能使玻璃球摔碎的最低楼层是临界点,不能使玻璃球摔碎的最高楼层也是临界点,当玻璃球将2个相邻临界楼层都查找过后,才能确定能使玻璃球摔碎的最低楼层。

可以说,临界楼层查找是二分查找的阉割版。

以二分查找关键字不在序列中的情况为原型,可以设计出各种各样的题目,例如LeetCode278题:第一个错误的版本

3. 方法研究

为叙述方便,首先定义如下变量:玻璃球个数 N N N查找楼层数 F F F临界楼层 F c F_c Fc最大查找次数 T M a x T_{Max} TMax平均查找次数 T T T最大摔碎球数 B M a x B_{Max} BMax平均摔碎球数 B B B

3.1 玻璃球数量充足的情况

当玻璃球数量充足时,无需顾忌玻璃球不够用的问题,因此可以直接使用二分查找算法进行临界楼层查找,并用二叉查找树(二叉排序树二叉搜索树)存储具体的查找策略。

结论1:由二分查找的思想易知,本文的二叉查找树一定是广度优先的

在二分查找中,如果某区间为[0, 2k+1] (k=0,1,2,…),那么该区间的中点可以取k,也可以取k+1,因此对应的二叉查找树结构不唯一。当 N N N=5, F F F=17时,二叉查找树有2种结构,如图1和图2所示,节点中的数字代表楼层序号。查找策略就是从根节点开始查找,若当前节点值大于等于临界值(玻璃球摔碎,数量减1),则继续查找当前节点的左子节点,若小于临界值(没有摔碎),则继续查找右子节点,依此类推,直到查找到空节点为止,最后一次使玻璃球摔碎的楼层即为临界楼层

既然要找最优策略,那么图1和图2中的二叉查找树存储的策略哪个更胜一筹呢?接下来从查找次数和摔碎球数两个角度进行比较。

3.1.1 查找次数

由查找策略可知,任意临界楼层对应的查找次数均为二叉查找树的根节点到某特定空节点的查找路径长度(即查找路径中非空节点的个数)

在图1中,二叉查找树一共有18个空节点,其中节点8和17的左右子节点对应查找路径长度为5,其余空节点对应查找路径长度均为4。但由于17层已经是最高层了,所以不可能查找节点17的右子节点。因此, T M a x T_{Max} TMax=5, T T T=(5×(4-1)+4×14)/17=4.18。

在图2中,二叉查找树同样有18个空节点,其中节点1和10的左右子节点对应查找路径长度为5,其余空节点对应查找路径长度均为4。同理,节点17的右子节点不会被查找。因此, T M a x T_{Max} TMax=5, T T T=(5×4+4×(14-1))/17=4.24>4.18。

因此,从查找次数的角度来看,图1中的二叉查找树最优。

结论2:为使查找次数最小,二叉查找树的最后一层最右边的节点要放在上一层最右边节点的右子节点位置,而最后一层的其它节点不论如何分布,平均查找次数都会始终保持最小值

3.1.2 摔碎球数

由查找策略可知,任意临界楼层对应的摔碎球数均为二叉查找树的根节点到临界楼层对应节点的查找路径(以下简称为查找路径)中左子节点个数加1

在图1中,当 F c F_c Fc为1时,摔碎球数为4;当 F c F_c Fc为2、3、5、10时,摔碎球数为3;当 F c F_c Fc为4、6、7、8、11、12、14时,摔碎球数为2;当 F c F_c Fc为9、13、15、16、17时,摔碎球数为1。因此, B M a x B_{Max} BMax

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值