DSA 中的超级鸡蛋掉落问题2025年2月7日 | 阅读 9 分钟 问题陈述在此问题陈述中,您有一个标有 1 到 n 的 n 层高的建筑,并且我们有 k 个相同的鸡蛋。任何在高于 f 的楼层丢下的鸡蛋都会破裂,任何在或低于楼层 f 丢下的鸡蛋都不会破裂,因为我们知道存在一个楼层 f,其中 0 <= f <= n。在每次移动中,您可以从任何楼层 x(其中 1 <= x <= n)丢下一个完好的鸡蛋。如果鸡蛋破裂,它将不再可用。如果鸡蛋没有破裂,您可以在后续的移动中再次使用它。 返回确定 f 值所需的最小步骤数,以确保准确性。 示例 1输入: k = 1, n = 2 输出 2 说明- 从第一层(第 1 层)开始丢下鸡蛋。
- 如果鸡蛋破裂,则 f = 0。
- 如果鸡蛋没有破裂,则继续下一步。
- 如果从第一层丢下的鸡蛋没有破裂,则从第二层(第 2 层)丢下鸡蛋。
- 如果鸡蛋破裂,则 f = 1。
- 如果鸡蛋没有破裂,则 f = 2。
- 在最坏的情况下,我们可能需要两次移动才能确切知道 f 的值。
- 因此,需要两次移动是最小的。
示例 2输入: k = 2, n = 6 输出 3 说明首先,从第二层(第 2 层)丢下第一个鸡蛋。 - 如果鸡蛋破裂,则 f = 1。
- 如果鸡蛋没有破裂,则继续下一步。
剩下一个鸡蛋,我们可以通过采用二分查找策略来减少查找 f 所需的移动次数。我们可以从一个将剩余楼层分成两半的楼层丢下第二个鸡蛋。在这种情况下,我们可以从第四层(第 4 层)丢下鸡蛋。 - 如果鸡蛋破裂,则 f = 3。
- 如果鸡蛋没有破裂,则继续下一步。
- 如果从第四层丢下的第二个鸡蛋没有破裂,我们可以确定 f = 5。
- 在最坏的情况下,可能需要 3 次移动才能准确地确定 f 的值。
因此,需要 3 次移动是最小的。 Java 动态规划方法输出 
 代码解释计算最小尝试次数的方法 我们需要初始化一个二维数组 dp 来存储数组子问题的结果。 遍历从 1 到 n 的每一层 - 迭代从 1 到 k 的每个鸡蛋
- 使用动态规划来计算当前配置的鸡蛋和楼层所需的最小尝试次数。
- 动态规划公式为 dp[j][i] = dp[j - 1][i - 1] + dp[j][i - 1] + 1,表示
- dp[j - 1][i - 1]:鸡蛋在第 i 层破裂时的尝试次数,少一个鸡蛋和一个楼层
- dp[j][i - 1]:鸡蛋在第 i 层没有破裂时的尝试次数,鸡蛋数量相同,楼层数少一个。
- 1:当前尝试
- 检查当前尝试次数是否超过或等于楼层数。如果是,则返回当前尝试次数。
如果尝试次数未超过楼层数,则返回 -1。 时间复杂度- SuperEggDrop 方法的时间复杂度为 O(k * n),其中 k 是鸡蛋的数量,n 是楼层的数量。这是因为存在嵌套循环。
空间复杂度- 空间复杂度为 O(k * n),因为它还包含一个维度为 (k+1)* (n+1) 的二维数组 dp,用于存储子问题结果。这会创建一个空间复杂度,其增长与鸡蛋和楼层的数量成正比,从而导致二次空间复杂度。
使用记忆化的 Java 实现输出 
 代码解释计算最小尝试次数的方法 - 初始化一个二维数组 dp 来存储子问题的结果。
- 调用 sol 方法以递归方式查找解决方案。
- 返回 sol 方法获得的结果。
递归方法 (sol)- 基本情况
- 如果只有一个鸡蛋(k == 1),或者没有楼层(n == 0 或 n == 1),则返回 n(楼层数)。
- 如果当前状态的解决方案已计算完毕(记忆化),则返回它。
- 初始化二分查找的下界(l)和上界(h)。
- 初始化答案(ans)为一个很大的值(Integer.MAX_VALUE)。
- 执行二分查找以找到最优解
- 计算下界和上界之间的中点(mid)。
- 递归查找鸡蛋破裂和鸡蛋未破裂两种情况的解决方案。
- 计算当前 mid 所需的移动次数。
- 根据二分查找的结果更新答案并调整边界。
- 记忆化结果并返回它。
时间复杂度- 该算法的时间复杂度为 O(k * n * log n),其中 k 是鸡蛋的数量,n 是楼层的数量。然而,困难来自于嵌套循环,它们处理所有可能的组合,以及这些循环中的二分查找。
空间复杂度- 空间复杂度为 O (k n),因为存储子问题结果的 dp 数组是动态的,需要空间。该数组由元素组成,其维度与鸡蛋和楼层的数量成正比。此外,由于需要重复所有嵌套的鸡蛋和楼层组合的时间,递归栈空间受 O(k * n) 的限制。
使用递归和二分查找的 Java 实现输出 
 代码说明递归辅助方法 (helper) - 基本情况
- 如果只有一个鸡蛋(k == 1),则返回楼层数(n)。
- 如果没有楼层(n == 0)或只有一层(n == 1),则返回楼层数(n)。
- 初始化 ans
- 初始化一个变量 ans 来存储最小尝试次数,从最大值开始。
- 遍历所有楼层
- 迭代每个楼层(k)以查找最小移动次数。
- 对于每个楼层,计算鸡蛋破裂(ans1)和鸡蛋未破裂(ans2)的最小移动次数。
- 计算总移动次数(ans3)为 ans1 和 ans2 之间的最大移动次数,再加上 1(当前移动)。
- 将 ans 更新为当前值与先前 ans 之间的最小值。
- 返回最小移动次数(ans)。
记忆化辅助方法 (helperDp) - 基本情况和记忆化
- 与 helper 方法相同。
- 如果当前状态的结果已计算,则从记忆化数组中返回它。
- 递归计算
- 记忆化结果
带有二分查找的记忆化辅助方法 (helperBs) - 基本情况和记忆化
- 通过二分查找优化解决方案
- 执行二分查找以找到最优解决方案。
- 根据递归调用的结果调整搜索范围。
- 记忆化结果
时间复杂度- 该算法的时间复杂度陈述为 O(k * n * log n) 的乘积,其中 k 和 n 分别是鸡蛋和楼层的数量。这个问题源于两个循环,它们都是递归的,因此是嵌套的;二分查找过程在 helperBs 方法中加剧了这个问题。
空间复杂度- 该算法的空间复杂度为 O(k * n),其中 k 是鸡蛋的数量,n 是楼层的数量。在此内存槽中,存在一个填充了记忆化(DP)的数组,旨在确保每次计算至少一次就足够了。
|