Leetcode 458. 可憐的小豬
鏈接:https://leetcode-cn.com/problems/poor-pigs
題意
有 buckets 桶液體,其中 正好 有一桶含有毒葯,其余裝的都是水。它們從外觀看起來都一樣。為了弄清楚哪只水桶含有毒葯,你可以喂一些豬喝,通過觀察豬是否會死進行判斷。不幸的是,你只有 minutesToTest 分鍾時間來確定哪桶液體是有毒的。
喂豬的規則如下:
選擇若干活豬進行喂養
可以允許小豬同時飲用任意數量的桶中的水,並且該過程不需要時間。
小豬喝完水后,必須有 minutesToDie 分鍾的冷卻時間。在這段時間里,你只能觀察,而不允許繼續喂豬。
過了 minutesToDie 分鍾后,所有喝到毒葯的豬都會死去,其他所有豬都會活下來。
重復這一過程,直到時間用完。
給你桶的數目 buckets ,minutesToDie 和 minutesToTest ,返回在規定時間內判斷哪個桶有毒所需的 最小 豬數。
示例 1:
輸入:buckets = 1000, minutesToDie = 15, minutesToTest = 60
輸出:5
示例 2:
輸入:buckets = 4, minutesToDie = 15, minutesToTest = 15
輸出:2
示例 3:
輸入:buckets = 4, minutesToDie = 15, minutesToTest = 30
輸出:2
提示:
1 <= buckets <= 1000
1 <= minutesToDie <= minutesToTest <= 100
算法
方法1:思維
先考慮二維的情況,假如有25個罐子
15分鍾死 | 30分鍾死 | 45分鍾死 | 60分鍾死 | 60分鍾活 | |
---|---|---|---|---|---|
15分鍾死 | 0 | 1 | 2 | 3 | 4 |
30分鍾死 | 5 | 6 | 7 | 8 | 9 |
45分鍾死 | 10 | 11 | 12 | 13 | 14 |
60分鍾死 | 15 | 16 | 17 | 18 | 19 |
60分鍾活 | 20 | 21 | 22 | 23 | 24 |
第一只去尋找列坐標,第二只去尋找行坐標。
第一只喝下在0分鍾喝下第一列的水(會在15分鍾后得到結果),15分鍾喝下第二列的水,30分鍾喝下第三列的水,45分鍾喝下第四列的水,進行k=4輪,總共有看k+ 1 = 5種狀態,那便可以確定一列。
那么同理,利用第二只豬可以確定行數。
那么同理,如果有三只豬,就可以確定三維的情況了。
\(((k + 1) ^ {res}) >= n => res >= \frac{\log _{2} n}{\log _{2}(k+1)}\)
方法2:香農熵
利用香農熵,代表信息量的大小,我們可以計算明確熵值,公式為:
其中 \(P(x)\) 代表隨機事件 \(x\) 的發生概率。
對於本題,記隨機事件 \(A\) 為 \(n\) 桶水中哪一個桶有問題,概率為 \(\frac{1}{n}\) 。
\(n\)桶水中有一桶水有問題香農熵(信息量)H(A):
記隨機事件 \(B\) 為在測試輪數為 \(k\) 時,所有實驗對象的最終狀 態,每個實驗對象的狀態共有 \(k+1\) 種,即共有 \(C=(k+1)^{m}\) 種最終結果,可近似看做等概率 \(\frac{1}{C}\) 。
我們需要求得在滿足 \(H(A)<=H(B)\) 前提下的最小 \(m\) 值。 代入公式可得:
移項化簡得:
class Solution {
public:
int poorPigs(int buckets, int minutesToDie, int minutesToTest) {
return ceil(log(buckets) / log(minutesToTest / minutesToDie + 1));
}
};