力扣题目
解题思路
java代码
力扣题目:
给你 k
枚相同的鸡蛋,并可以使用一栋从第 1
层到第 n
层共有 n
层楼的建筑。
已知存在楼层 f
,满足 0 <= f <= n
,任何从 高于 f
的楼层落下的鸡蛋都会碎,从 f
楼层或比它低的楼层落下的鸡蛋都不会破。
每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x
扔下(满足 1 <= x <= n
)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。
请你计算并返回要确定 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
解题思路:
算法原理:
这道题使用了动态规划和备忘录的方法来解决鸡蛋掉落的问题,以找到在给定鸡蛋数量和楼层数量的情况下,确定最少的尝试次数能保证找到鸡蛋恰好不碎的楼层。
思路:
- 定义一个备忘录
memo
来存储已经计算过的结果,避免重复计算。 dp
函数接受鸡蛋数量k
和楼层数量n
作为参数。- 如果楼层数为 0 ,返回 0 。
- 如果只有 1 个鸡蛋,返回楼层数
n
。 - 对于其他情况,通过二分搜索来确定一个尝试的楼层
x
。 - 根据在
x
楼扔鸡蛋后的结果,更新搜索范围lo
和hi
。 - 最终计算并返回最少的尝试次数,取在不同尝试楼层
lo
和hi
下的最坏情况的最小值加 1 。
代码分析:
- 在
dp
函数中,首先检查备忘录中是否已经有计算结果,如果没有则进行计算并存储。 - 二分搜索部分通过比较不同尝试楼层下碎与不碎的情况来调整搜索范围。
时间复杂度:,其中 k
是鸡蛋数量,n
是楼层数量。
空间复杂度:,用于存储备忘录中的结果。
java代码:
package com.example.lib;
import java.util.HashMap;
import java.util.Map;
public class Leetcode887 {
public static void main(String[] args) {
Leetcode887 leetcode887 = new Leetcode887();
int ans = leetcode887.superEggDrop(2, 6);
System.out.println(ans);
}
// 鸡蛋掉落
Map<Integer, Integer> memo = new HashMap<Integer, Integer>();
public int superEggDrop(int k, int n) {
return dp(k, n);
}
public int dp(int k, int n) {
if (!memo.containsKey(n * 100 + k)) {
int ans;
if (n == 0) {
ans = 0;
} else if (k == 1) {
ans = n;
} else {
int lo = 1, hi = n;
while (lo + 1 < hi) {
int x = (lo + hi) / 2;
int t1 = dp(k - 1, x - 1);
int t2 = dp(k, n - x);
if (t1 < t2) {
lo = x;
} else if (t1 > t2) {
hi = x;
} else {
lo = hi = x;
}
}
ans = 1 + Math.min(Math.max(dp(k - 1, lo - 1), dp(k, n - lo)), Math.max(dp(k - 1, hi - 1), dp(k, n - hi)));
}
memo.put(n * 100 + k, ans);
}
return memo.get(n * 100 + k);
}
}
更多详细内容同步到公众号,感谢大家的支持!
每天都会给刷算法的小伙伴推送明日一题,并且没有任何收费项