leetcode458 可怜的小猪

leetcode458 可怜的小猪

有 1000 只水桶,其中有且只有一桶装的含有毒药,其余装的都是水。它们从外观看起来都一样。如果小猪喝了毒药,它会在 15 分钟内死去。

问题来了,如果需要你在一小时内,弄清楚哪只水桶含有毒药,你最少需要多少只猪?

回答这个问题,并为下列的进阶问题编写一个通用算法。

进阶:

假设有 n 只水桶,猪饮水中毒后会在 m 分钟内死亡,你需要多少猪(x)就能在 p 分钟内找出 “有毒” 水桶?这 n 只水桶里有且仅有一只有毒的桶。

提示:

可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。
小猪喝完水后,必须有 m 分钟的冷却时间。在这段时间里,只允许观察,而不允许继续饮水。
任何给定的桶都可以无限次采样(无限数量的猪)

这道题很有意思,在LeetCode上是困难级别,难就难在如何抽象出这个题的本质?

假设现在我们只有一只猪,那么能够检测出多少桶水中有一桶水有毒呢?

你不用想都知道是5桶,只要让这只猪分别在0分钟,15分钟,30分钟,45分钟喝依次喝水,猪的状态可能为死在15,30,45,60分钟,或者没死,就可以判断出哪桶水有毒。

如果我们现在又两只猪,那么可以检测多少桶水中有一桶水有毒呢?

你不用想都知道是10桶,我依次让猪把十桶水喝下去不就能测出来了? 我呸,如果你这么想就。。。

答案应该是25桶,每只猪在一个小时内都有五种状态,那么两只猪组合在一起,一个小时就有25种状态,这就好比一只猪代表一个5进制数的一位,那么两只猪就有两位五进制数,可以表示0-24,给25桶水标记上0-24。我们同时让两只猪喝这个五进制数每一位上的0,1,2,3,4**(为什么可以同时喝这个五进制数上的位?题目不是说了可以同时喝吗!**),当某只猪死了,另外一只猪继续喝下去,直到它死了还是没死。比如说两只猪喝到(13)过了15分钟死了,代表编号为8的水桶有毒,喝到(24)过了15分钟死了,代表编号为14的水桶有毒,如果两只猪一只喝到(44)过了15分钟还没死,那说明什么?没说明什么,因为这种情况不可能出现,(44)代表编号为24的水桶,喝完了最后一桶还没死,说明水里根本没毒。

抽象出来,这其实是一个进制问题,两只猪可以表示的五进制数对应十进制最多为25,3只猪表示的五进制数对应十进制为53=125。那么5只猪表示的5进制数>1000,所以用5只猪就可以找到1000个水桶有毒的情况,用上述依次喝的办法就能找到是哪个编号的水桶有毒。

那么这道题mark=int(p/m)+1决定一只小猪一共几种状态,即几进制数,如果水的桶数为n(进制数能够表示的范围), 那么 i n t ( log ⁡ m a r k ( n ) ) + 1 int(\log_{mark}\left(n\right))+1 int(logmark(n))+1就是需要的小猪个数。

下面就是解题代码

class Solution:
    def poorPigs(self, buckets: int, minutesToDie: int, minutesToTest: int) -> int:
        mark = int(minutesToTest/minutesToDie)+1
        for i in range(100):
            if mark**i>=buckets:
                return i

你可能感兴趣的:(LeetCode)