面试题:检测杯子的质量

分享一道最近刷到的面试题:

有一种玻璃杯质量确定但未知,需要检测。   
有一栋100层的大楼,该种玻璃杯从某一层楼扔下,刚好会碎。   
现给你两个杯子,问怎样检测出这个杯子的质量,即找到在哪一层楼刚好会碎?


看到这道题的时候我自然地想,从一楼开始扔起...这还不简单?然而之前面试挂掉的经验让我知道,这时候面试官一定会问:

面试官的微笑.jpg

“你再多想想?有没有更快的方法?”


首先要分析一下题目,和面试官争取一波思考的时间:

1、两个杯子质量一样;

2、如果杯子在第N楼扔下去没有碎,那在小于N楼扔下去也不会碎;

3、如果杯子在第N楼扔下去碎了,那就得往小于N楼继续检验(但杯子只有两个);

4、如果杯子扔下去没碎,还能反复利用。

总的来说就是,通过有限的两个杯子,快速找到在第N-1楼扔下去不碎而第N楼扔下去会碎的这个楼层N。


方案一:二分法

这不就是查找吗,不过得保证在杯子用完之前能找到这个楼层,作为一个朴实的算法菜鸟,我首先就想到了——二分法

先从50楼扔下去一个杯子,没碎的话就往上走,从75楼扔下去,没碎就继续,直到找到刚刚好碎掉的楼层。然而事情不会这么顺利,在这种方案下我们只能往上走。一旦第一个杯子碎了,就得从最低楼层往上找了,比如说:我从50楼扔下去,没碎,再从75楼扔下去,碎了,这时候只能从51层开始往上尝试,如果刚好结果是74楼的话,总共得扔1+24=25次。所以最坏的情况也出来了:从50楼扔下去,碎了,然后乖乖从1楼开始往上试,如果刚好结果是49楼的话,总共得扔1+49=50次。

面试官:“还行,次数少了一半了,你再多想想?


方案二:分段查找

如果二分不行,那就把区间分得比二分再细一些,也就是分段地扔,比如说把100楼分成10段,从10楼开始往上,逐十楼地扔。

这样最好的情况是:从10楼扔下去刚好碎了,从1楼开始试,假如恰好在9楼碎了,那总共得扔1+9=10次。

最差的情况是:从10楼开始扔,没碎,继续走到20楼开始扔,也没碎,一直到了100楼扔下去碎了,然后从91楼开始往上尝试,假如恰好在99楼碎了,总共得扔10+9=19次。

面试官:“可以,更快了,但我不想多跑几次,能不能告诉我最少扔几次就能确定出楼层?”


方案三:解方程

这么说有理论上的最少尝试次数?其实从前面两种方案能够看出我们试错的规律:假如我只需要扔x次,那必须得从第x楼开始扔,这是因为碎了的话,我还可以尝试前面的x-1楼,确保能够找到目标楼层。那根据碎和不碎就有两种情况:

  • 如果第一个杯子从x楼扔下去碎了,第二次就从x+(x-1)楼开始尝试,如果还没碎,那第三次就到x+(x-1)+(x-2)楼尝试,就依此类推......
  • 如果中途碎了,我们有x-m次尝试机会回去尝试,能够以少于x-m次机会找到目标楼层。

假如经过x次尝试能够到达的最高楼层就是x+(x-1)+(x-2)+ ... +1=x(x+1)/2,如果最高楼层是100,那求解x(x+1)/2>=100,得到x>=14,即按上述方案至多尝试14次就能确保找到目标楼层,所以最少尝试次数就是14次。

相信此时面试官已经满意了,但是我不满意了。

面试官的微笑.jpg

“万一下次它问我3个杯子怎么办?再多想想?


方案四:动态规划推广

当我们只有一个杯子的时候,其实能做的事情只有从低楼层开始往上尝试。有了两个以上的杯子就有了多次试错的机会,减少尝试的次数。如果只要找到最优解,那可以通过动态规划,将N个杯子的问题拆成N-1个杯子的子问题和1个用于试错的杯子。

将问题标记为W(n,k),其中 n 代表可用于测试的杯子数,k 代表被测试的楼层数。

对于问题 W(2,100), 我们可以如此考虑:

  • 将第 1 个杯子,在第 i 楼扔下( i 可以为 1~k 的任意值),如果碎了,则我们需要用第 2 个杯子,解决从第 1 楼到第 i-1 楼的 子问题 W(1,i-1)

  • 如果这个杯子没碎,则我们需要用这两个杯子,解决从 i+1 楼到第 100 楼的子问题 W(2,100-i)

解决上述的两个子问题后,我们可以取两者中尝试次数最多的方案(排除掉因为欧气快速找到楼层的情况,确保能够找到目标楼层),与在第 i 楼尝试的这次相加,即得到了在第 i 层扔下杯子时 W(2,100)这个问题的最少尝试次数。

而在所有杯子从100楼中任意楼层扔下去,产生的100个测试方案,它们的尝试次数恒大于等于一个理论上最少的尝试次数T,这个T就是本问题的答案。

递推公式:

W(n, k) = 1 + min{max(W(n -1, x -1), W(n, k - x))}, x in {2, 3, ……,k}

同理,我们可以拓展N个杯子、M个楼层的问题!

面试官的微笑.jpg

我:“我还能想,别拦着我!”

发布了5 篇原创文章 · 获赞 7 · 访问量 870

猜你喜欢

转载自blog.csdn.net/qq_40340478/article/details/105172516
今日推荐