题目
你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
示例 1:
输入:K = 1, N = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。
否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。
如果它没碎,那么我们肯定知道 F = 2 。
因此,在最坏的情况下我们需要移动 2 次以确定 F 是多少。
示例 2:
输入:K = 2, N = 6
输出:3
示例 3:
输入:K = 3, N = 14
输出:4
提示:
1 <= K <= 100
1 <= N <= 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/super-egg-drop
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
这是一道困难的题目,推荐基础了解李永乐老师讲解的双蛋问题。
思路来说,leetcode官方题解中的第三种解法反而最容易懂,所以本文就讲述一下我搞懂了的第三种方法。
已知
本题要求解的是N层楼使用K个鸡蛋,至少扔M次能找到临街楼层F。
又可解读为
用K个鸡蛋,操作T次,能找到最高的楼层是多少?需要满足最高楼层>=N。所以需要找出最小能满足f(T,K)>=N的T值
递归(动态规划)思考过程
关于f(T,K)怎么求,我们思考一下扔出一个鸡蛋,看看到底发生了什么:
如果鸡蛋没有碎,那么对应的是 f(T - 1, K),也就是说在这一层的上方可以有 f(T - 1, K) 层;
如果鸡蛋碎了,那么对应的是 f(T - 1, K - 1),也就是说在这一层的下方可以有 f(T - 1, K - 1)层。
因此我们就可以写出状态转移方程:
f(T, K) = 1 + f(T-1, K-1) + f(T-1, K)
边界条件为:当 T≥1 的时候 f(T, 1) = T,当 K≥1 时,f(1,K)=1。
那么T 最大可以达到多少?由于操作次数是一定不会超过楼层数的,因此 T≤N,我们只要算出在 f(N, K)内的所有 f 值即可。
go code
基础代码
func superEggDrop(K int, N int) int {
if N==1 {
return 1
}
var f [][]int
for i:=0;i<=N;i++ {
item := make([]int,K+1)
f = append(f,item)
}
for i:=1;i<=K;i++ {
f[1][i] = 1
}
ans := -1
for i:=2;i<=N;i++ {
for j:=1;j<=K;j++ {
f[i][j] = 1+f[i-1][j-1]+f[i-1][j]
}
if f[i][K]>=N {
ans = i
break
}
}
return ans
}
进阶优化代码
func superEggDrop(K int, N int) int {
times := 1
for {
if getTimes(times, K) >= N {
break
}
times ++
}
return times
}
func getTimes(times, eggCount int) int {
if times == 1 || eggCount == 1{
return times
}
return getTimes(times - 1, eggCount - 1) + 1 + getTimes(times - 1, eggCount)
}
总结
- 遇到难题时,还是要回归到基础的一些思想
- 比如本题学到的基础思想是递归