来自Math Battle的问题。 在我的一次求职面试中,我也问过这个特别的问题。
“一只猴子有两个椰子。从阳台上扔椰子是骗人的 M层建筑。当椰子被打破时,猴子想要知道最低楼层。 确定这一事实所需的最小尝试次数是多少? “条件:如果椰子被破坏,你就不能重复使用。你只剩下另一个椰子
我能想到的可能的方法/策略是
想知道是否有其他方法可以做到这一点。
答案 0 :(得分:15)
这样的面试问题旨在让您了解自己的想法。所以我可能会提到如上所述的O(N ^ 0.5)解决方案,但我也会给出以下讨论......
由于椰子可能会随着时间的推移而发生内部开裂,因此结果可能与O(N ^ 0.5)溶液不一致。虽然O(N ^ 0.5)解决方案是有效的,但它并不完全可靠。
我会推荐使用第一个椰子的线性O(N)溶液,然后用第二个椰子验证结果。其中N是建筑物中的楼层数。所以对于第一个椰子你尝试一楼,然后是第二个,然后是第三个,...
假设两个椰子在结构上完全相同并且以完全相同的角度掉落,那么你可以将第二个椰子直接扔在第一个椰子破坏的地板上。把这个椰子破碎的地板称为B.
对于椰子#2,你不需要在1..B-1上进行测试,因为你已经知道第一个cocounut没有在B-1,B-2楼层上破坏...... 1.所以你只需要在B上试一试。
如果第二个椰子在B上破裂,那么你知道B是有问题的地板。如果它没有破裂你可以推断出椰子会随着时间的推移而发生内部开裂和降解,并且测试开始时是有缺陷的。你需要更多的椰子。
鉴于建筑面积非常有限,您对解决方案的额外信心值得O(N)解决方案。
正如@RafałFowgird所说,解决方案还取决于所讨论的猴子是非洲猴还是欧洲猴。众所周知,非洲猴子的力量更大。因此,使破碎地板B仅准确地具有+/- 2层的变化。
为了保证猴子不会因为所有这些楼梯而感到疲倦,建议在第一个椰子上附上一根绳子。这样你就不需要为第一个椰子做1 + 2 + .. + B = B *(B + 1)/ 2级楼梯。你只需要做B级楼梯。
看起来楼梯的数量与这个问题无关,但如果猴子一开始就累了,我们可能永远不会找到解决方案。这为halting problem提供了新的考虑因素。
我们还假设建筑物位于地球上,重力设定为9.8m / s ^ 2。我们还假设不存在引力波。
答案 1 :(得分:8)
二分搜索不是答案,因为你只有一次机会高估。二进制搜索需要log m
次最大估计。
这是一个两阶段的方法。首先是以相对较大的步骤迭代地板。在第一个椰子破碎后,第二个阶段是在最后一个安全地板后开始尝试每个楼层。
大步骤大致为sqrt(m)
,但它们早期较大,后期较小,因为如果第一个椰子早期破裂,您可以在第二阶段进行更多迭代。
StepSize = (minimum s such that s * (s + 1) / 2 >= m)
CurrentFloor = 0
While no coconuts broken {
CurrentFloor += StepSize
StepSize -= 1
Drop coconut from CurrentFloor
}
CurrentFloor -= StepSize + 1
While one remains coconut unbroken {
CurrentFloor += 1
Drop remaining coconut from CurrentFloor
}
// CurrentFloor is now set to the lowest floor that will break the coconut,
// using no more total drops than the original value of StepSize
答案 2 :(得分:2)
我知道的最佳解决方案是2 * sqrt(n)。从sqrt(n),2 * sqrt(n),......到n(或直到它破裂)放下第一个椰子。然后从最后一个已知的“安全”点放下第二个,以一层为增量,直到它断开。两个阶段最多只有sqrt(n)次投掷。
编辑:您可以在O(sqrt(n))内改进常量,请通过递归查看注释。我认为第一步应该在sqrt(2 * n)左右,并且每次抛出减少1,所以最后一步(如果破碎高度实际上是n)正是1.详细信息由读者计算:)
答案 3 :(得分:2)
由于这是一个面试问题,请考虑
昂贵的操作是猴子上下楼梯,而不是扔椰子。以这种方式思考,“线性”方法实际上是N 2 。
通过下落赋予椰子的能量大致与下落的高度成比例。如果壳体在吸收一定量的能量后被破坏了......
答案 4 :(得分:1)
艰难的面试问题。我花了好几天。
我相信尝试次数是地板数的SQRT的1.5倍。 (100层和2层可可15层)
我们希望尽量减少每次尝试的大小和尝试次数,同时使用它们来覆盖所有可能的楼层。在这种情况下,sqroot结果是一个很好的起点,但我们会改变每个尝试的大小并在sqroot附近平均。 这样我们就拥有了两全其美的优势:每个尝试的大小均匀分布在sqroot周围,这给我们带来了最好的结果。对于100和2,这是15,14,13,12,11,10,9,8,7,6 这可以达到1.5倍。