题目
- 鸡蛋掉落
题目描述
你将获得K个鸡蛋,并可以使用一栋从1到N共有N层楼的建筑
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层F,满足0 <= F <= N 任何从高于F的楼层落下的鸡蛋都会碎,从F楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层X扔下(满足 1 <= X <= N)。
你的目标是确切地知道F的值是多少。
无论F的初始值如何,你确定F的值的最小移动次数是多少?
案例
示例一
输入:K = 1, N = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。
否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。
如果它没碎,那么我们肯定知道 F = 2 。
因此,在最坏的情况下我们需要移动2次以确定F是多少。
示例二
输入:K = 2, N = 6
输出:3
示例三
输入:K = 3, N = 14
输出:4
提示
1 <= K <= 100
1 <= N <= 10000
思路
已知条件:K个鸡蛋,N层楼
有什么状态?
就是发生变化的量,已知存在两个,当前拥有的鸡蛋数K,需要测试的楼层数N,随着测试的进行,鸡蛋个数会减少,
楼层个数可能减少,这就是状态的变化。
有什么选择?
去哪层楼扔鸡蛋
状态转移
如果选择第i层扔鸡蛋
如果鸡蛋碎了 K->K-1, 0 ~ N->0 ~ i-1
如果鸡蛋没碎 K->K, 0~N -> i+1 ~ N
代码
package leetcode
import (
"fmt"
)
// superEggDrop
// 887. 鸡蛋掉落
func superEggDrop(K int, N int) int {
// 备忘录解决重叠子问题
meno := map[string]int{}
var dp func(K, N int) int
dp = func(K, N int) int {
// base case
// 楼层为0
if N == 0 {
return 0
}
// 只有一个鸡蛋
if K == 1 {
return N
}
// 校验备忘录中是否存在
key := fmt.Sprintf("%d%d", K, N)
if rs, ok := meno[key]; ok {
// log.Println(rs)
return rs
}
res := 1<<31 - 1
for i := 1; i <= N; i++ {
// 最坏情况
// 鸡蛋没碎:K->K, 0~N -> i+1 ~ N
// 鸡蛋碎了:K->K-1, 0~N -> 0 ~i-1
maxNums := max(dp(K, N-i), dp(K-1, i-1)) + 1
// 最少扔鸡蛋次数
res = min(res, maxNums)
}
meno[key] = res
return res
}
return dp(K, N)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
// superEggDrop
// 887. 鸡蛋掉落
// 使用二分法提升效率
func superEggDropV2(K int, N int) int {
// 备忘录解决重叠子问题
meno := map[string]int{}
var dp func(K, N int) int
dp = func(K, N int) int {
// base case
// 楼层为0
if N == 0 {
return 0
}
// 只有一个鸡蛋
if K == 1 {
return N
}
// 校验备忘录中是否存在
key := fmt.Sprintf("%d%d", K, N)
if rs, ok := meno[key]; ok {
return rs
}
res := 1<<31 - 1
left, right := 1, N
for left <= right {
mid := (left + right) / 2
// 碎了
broken := dp(K-1, mid-1)
// 没碎
notBroken := dp(K, N-mid)
if broken > notBroken {
right = mid - 1
res = min(res, broken+1)
} else {
left = mid + 1
res = min(res, notBroken+1)
}
}
meno[key] = res
return res
}
return dp(K, N)
}
参考
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/su…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
[算法小抄@付东来]