

文章目录
摘要
这道题乍一看是个"喂猪试毒"的奇怪问题,但本质其实是一个信息量 + 状态数 的问题。你不是在算猪,而是在算:
在有限的时间里,一只猪最多能帮你区分多少种情况?
一旦想明白这一点,这题就会从"完全没思路"瞬间变成"哦,原来是这样"。

描述
题目给你一堆桶,外观完全一样,其中正好有一桶有毒 。
你手里有一些小猪,可以喂它们喝水,通过观察"死 / 活"来判断毒桶是哪一个。
但有几个非常关键的限制:
- 猪喝完水后,要等
minutesToDie分钟才能知道它会不会死 - 在这段等待时间内,不能再喂
- 总时间只有
minutesToTest分钟 - 一只猪在一次喂水中,可以喝任意多个桶
- 目标是:用最少的猪,在规定时间内,100% 确定毒桶
乍一看像是实验设计题,但其实是一个离散数学 + 编码问题。
题解答案
核心结论一句话:
如果一只猪在整个测试过程中可以产生
states种不同结果,那么p只猪最多可以区分states^p个桶。
只要满足:
states^p >= buckets
最小的 p,就是答案。
题解代码分析
先搞清楚"一只猪有多少种状态"
假设:
rounds = minutesToTest / minutesToDie
也就是说,你最多能喂 rounds 次。
那一只猪会有哪些可能结果?
- 第 1 轮死
- 第 2 轮死
- ...
- 第 rounds 轮死
- 一直没死(说明没喝到毒)
所以:
states = rounds + 1
这一点非常关键,也是整道题的"转折点"。
为什么是指数关系?
你可以把每一只猪当成一个"多进制位"。
- 每只猪有
states种状态 p只猪一共能表示states^p种不同组合- 每一种组合,对应一个桶
这其实和 二进制编码 一模一样,只不过这里不是 0/1,而是多状态。

Swift 实现思路
实现非常简单:
- 先算出
states - 从 0 开始,不断增加猪的数量
- 直到
states^p >= buckets
可运行 Swift Demo 代码
swift
import Foundation
class Solution {
func poorPigs(_ buckets: Int, _ minutesToDie: Int, _ minutesToTest: Int) -> Int {
// 能进行多少轮测试
let rounds = minutesToTest / minutesToDie
// 每只猪的状态数(在哪一轮死,或者一直活着)
let states = rounds + 1
var pigs = 0
var capacity = 1
// 逐步增加猪的数量
while capacity < buckets {
pigs += 1
capacity *= states
}
return pigs
}
}
这段代码是完全可以直接跑的,没有任何花里胡哨的地方,逻辑和数学推导是一一对应的。
示例测试及结果
我们用题目里的几个例子跑一遍。
swift
let solution = Solution()
print(solution.poorPigs(1000, 15, 60)) // 5
print(solution.poorPigs(4, 15, 15)) // 2
print(solution.poorPigs(4, 15, 30)) // 2
输出结果:
5
2
2
和题目给出的结果完全一致。
与实际场景结合
这道题在现实中,其实非常像下面几类问题:
-
分布式系统定位故障节点
- 每一轮探测相当于一次健康检查
- 每个节点返回的状态就是"猪的状态"
-
A/B 实验中的多轮用户行为分析
- 不同轮次的行为组合,本质也是状态编码
-
压缩测试资源
- 用更少的"探针",在有限轮次内覆盖更多可能性
本质都是一句话:
在资源有限的情况下,最大化信息量。
时间复杂度
O(p)
其中 p 是最终需要的猪的数量。
由于 buckets <= 1000,p 最大也就 5~6,基本可以忽略。
空间复杂度
O(1)
只用了几个整数变量,没有额外的数据结构。
总结
这道题最容易卡人的地方,并不是代码,而是建模思路。
一旦你意识到:
- 猪不是"工具",而是"多状态编码器"
- 死亡轮次本身就是信息
- 多只猪就是指数级组合
整道题会瞬间从"完全没头绪",变成"非常优雅"。