【经典算法题】可怜的小猪
Leetcode 0458 可怜的小猪
题目描述:Leetcode 0458 可怜的小猪
分析
-
本题的考点:数学。
-
使用
n、m、p
来代表题目中的buckets、minutesToDie、minutesToTest
。则我们最多进行 k = ⌊ p m ⌋ k = \lfloor \frac{p}{m} \rfloor k=⌊mp⌋轮测试。 -
首先考虑一个简单情况,如果
k=1
,相当于我们只能进行一轮测试,则我们需要将猪看成二进制猪,将某桶水的编号转化为二进制,二进制下如果第i
位是1
则让第i
头猪喝这桶水,最后判断哪些猪死了,死的猪对应位为1,这样拼接得到有毒的水的编号。 -
k=1
时,需要 ⌈ l o g 2 ( n ) ⌉ \lceil log_2(n) \rceil ⌈log2(n)⌉ 头猪。猜想:k
轮的话,需要 ⌈ l o g k + 1 ( n ) ⌉ \lceil log_{k+1}(n) \rceil ⌈logk+1(n)⌉ 头猪。如下是证明: -
每只猪存在
k+1
中状态:k
轮测试后没死(用0
代表);第一轮后死了(用1
代表);第二轮后死了(用2
代表);…;第k
轮后死了(用k
代表)。 -
假设最后需要
x
头猪,则必须要满足 ( k + 1 ) x ≥ n (k+1)^x \ge n (k+1)x≥n,这样才能区分出每种状态,所以:
x ≥ ⌈ l o g k + 1 ( n ) ⌉ x \ge \lceil log _{k+1} (n) \rceil x≥⌈logk+1(n)⌉
- 我们可以构造出一种方案,使得取到下界,假设猪的编号是
0~x-1
,水的编号为0~n-1
,对于某桶水编号为y
,我们可以把y
看成一个k+1
进制数,这样y
有x
位,高位不足补0,如下图:
-
对于这个
k+1
进制数,考虑其某一位a[i]
,表示这桶水什么时候喂给第i
头猪:有k+1
种取值,即0~k
,如果为0
,则这桶水不喂给第i
头猪;为1
的话则第一轮喂给第i
头猪;…;为k
的话则第k
轮喂给第i
头猪。 -
对于有毒的那桶水,在
k+1
进制下,如何确定第i
位的大小呢?第i
头猪在在第几轮死,则这一位就是几,如果没死,就是0。
代码
- C++
class Solution {
public:
int poorPigs(int n, int minutesToDie, int minutesToTest) {
int k = minutesToTest / minutesToDie;
return ceil(log(n) / log(k + 1));
}
};
- Java
class Solution {
public int poorPigs(int n, int minutesToDie, int minutesToTest) {
int k = minutesToTest / minutesToDie;
return (int) Math.ceil(Math.log(n) / Math.log(k + 1));
}
}
时空复杂度分析
-
时间复杂度: O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。