418、可憐的小豬
有 1000 只水桶,其中有且只有一桶裝的含有毒藥,其餘裝的都是水。它們從外觀看起來都一樣。如果小豬喝了毒藥,它會在 15 分鐘內死去。
問題來了,如果需要你在一小時內,弄清楚哪隻水桶含有毒藥,你最少需要多少隻豬?
回答這個問題,併爲下列的進階問題編寫一個通用算法。
進階:
假設有 n 只水桶,豬飲水中毒後會在 m 分鐘內死亡,你需要多少豬(x)就能在 p 分鐘內找出 “有毒” 水桶?這 n 只水桶裏有且僅有一隻有毒的桶。
提示:
- 可以允許小豬同時飲用任意數量的桶中的水,並且該過程不需要時間。
- 小豬喝完水後,必須有 m 分鐘的冷卻時間。在這段時間裏,只允許觀察,而不允許繼續飲水。
- 任何給定的桶都可以無限次採樣(無限數量的豬)。
題解:
用信息論的概念來求解
- 一共有n個桶,要知道哪個桶有有毒藥,至少需要*math.log2(n)*的信息量(對數的底數取多少不影響信息量的計算)
- 每一隻豬可以測試的次數是t=math.floor(minutesToTest/minutesToDie)。每隻豬有t+1種狀態,在第i次死亡(i:[1,2,…,t],或者存活,帶信息量math.log2(t+1)
- 答案就是math.ceil[math.log2(n)/math.log2(t+1)]
代碼:
import math
class Solution(object):
def poorPigs(self, buckets, minutesToDie, minutesToTest):
"""
:type buckets: int 桶的數量
:type minutesToDie: int 幾分鐘死亡
:type minutesToTest: int 測試多長時間
:rtype: int 總共需要多少小豬
"""
number = math.floor(minutesToTest / minutesToDie)
return math.ceil(math.log2(buckets)/math.log2(number+1))