Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 362565d

Browse files
committed
Update 0887. 鸡蛋掉落.md
1 parent 12fccba commit 362565d

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

‎Solutions/0887. 鸡蛋掉落.md

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828

2929
## 解题思路
3030

31-
### 思路 1:动态规划(超时)
32-
33-
这道题目的题意不是很容易理解,我们先把题目简化一下,忽略一些限制条件,理解简单情况下的题意。然后再一步步增加限制条件,从而先弄明白这道题目的意思。
31+
这道题目的题意不是很容易理解,我们先把题目简化一下,忽略一些限制条件,理解简单情况下的题意。然后再一步步增加限制条件,从而弄明白这道题目的意思。以及思考解题思路。
3432

3533
我们先忽略 `k` 个鸡蛋这个条件,假设有无限个鸡蛋。
3634

@@ -43,7 +41,7 @@
4341
- 如果鸡蛋没摔碎,则可以继续选择其他楼层进行测试。
4442
- 如果鸡蛋摔碎了,则该鸡蛋无法继续测试。
4543

46-
现在题目要求:一共有 `n` 层楼,无限个鸡蛋,求出至少需要扔几次鸡蛋,才能保证无论 `f` 是多少层,都能将 `f` 找出来?
44+
现在题目要求:**已知有 `n` 层楼,无限个鸡蛋,求出至少需要扔几次鸡蛋,才能保证无论 `f` 是多少层,都能将 `f` 找出来?**
4745

4846
最简单且直观的想法:
4947

@@ -61,7 +59,7 @@
6159
- 如果鸡蛋碎了,则从第 `1` 层到中间层这个区间中去扔鸡蛋。
6260
- 如果鸡蛋没碎,则从中间层到第 `n` 层这个区间中去扔鸡蛋。
6361

64-
每次扔鸡蛋都从区间的中间层去扔,这样每次都能排除当前区间一半的答案,从而最终确定鸡蛋不会摔碎的最高楼层 `f`
62+
每次扔鸡蛋都从区间的中间层去扔,这样每次都能排除当前区间一半的答案,从而最终确定鸡蛋不会摔碎的最高楼层 `f`
6563

6664
通过这种二分查找的方法,可以优化到 $\log n$ 次就能确定鸡蛋不贵摔碎的最高楼层 `f`
6765

@@ -71,11 +69,13 @@
7169

7270
这是不限制鸡蛋个数的情况下,现在在给定 `n` 层楼的基础上,再限制一下鸡蛋个数为 `k`
7371

74-
现在题目要求:一共有 `n` 层楼,`k` 个鸡蛋,求出至少需要扔几次鸡蛋,才能保证无论 `f` 是多少层,都能将 `f` 找出来?
72+
现在题目要求:**已知有 `n` 层楼,`k` 个鸡蛋,求出至少需要扔几次鸡蛋,才能保证无论 `f` 是多少层,都能将 `f` 找出来?**
7573

7674
如果鸡蛋足够多(大于等于 $\log_2 n$ 个),可以通过二分查找的方法来测试。如果鸡蛋不够多,可能二分查找过程中,鸡蛋就用没了,则不能通过二分查找的方法来测试。
7775

78-
那么这时候为了找出 `f` ,我们应该如何求出最少的扔鸡蛋次数。
76+
那么这时候为了找出 `f` ,我们应该如何求出最少的扔鸡蛋次数?
77+
78+
### 思路 1:动态规划(超时)
7979

8080
可以这样考虑。题目限定了 `n` 层楼,`k` 个鸡蛋。
8181

@@ -146,7 +146,7 @@ class Solution:
146146

147147
### 思路 2:动态规划优化
148148

149-
上一步中时间复杂度为 $O(n^2 \times k)$。根据 $n$ 的规模,提交上去补出意外的超时了
149+
上一步中时间复杂度为 $O(n^2 \times k)$。根据 $n$ 的规模,提交上去不出意外的超时了
150150

151151
我们可以观察一下上面的状态转移方程 $dp[i][j] = min_{1 \le x \le n} (max(dp[i - x][j], dp[x - 1][j - 1])) + 1$ 。
152152

@@ -197,21 +197,55 @@ class Solution:
197197

198198
### 思路 3:动态规划 + 逆向思维
199199

200+
再看一下我们现在的题目要求:已知有 `n` 层楼,`k` 个鸡蛋,求出至少需要扔几次鸡蛋,才能保证无论 `f` 是多少层,都能将 `f` 找出来?
201+
202+
我们可以逆向转换一下思维,将题目转变为:**已知有 `k` 个鸡蛋,最多扔 `x` 次鸡蛋(碎没碎都算 `1` 次),求最多可以检测的多少层?**
203+
204+
我们把未知条件「扔鸡蛋的次数」变为了已知条件,将「检测的楼层个数」变为了未知条件。
205+
206+
这样如果求出来的「检测的楼层个数」大于等于 `n`,则说明 `1` ~ `n` 层楼都考虑全了,`f` 值也就明确了。我们只需要从符合条件的情况中,找出「扔鸡蛋次数」最少的次数即可。
207+
208+
动态规划的具体步骤如下:
209+
210+
###### 1. 划分阶段
211+
212+
按照鸡蛋个数、扔鸡蛋的次数进行阶段划分。
213+
214+
###### 2. 定义状态
215+
216+
定义状态 `dp[i][j]` 表示为:一共有 `i` 个鸡蛋,最多扔 `j` 次鸡蛋(碎没碎都算 `1` 次)的条件下,最多可以检测的楼层个数。
217+
218+
###### 3. 状态转移方程
219+
220+
我们现在有 `i` 个鸡蛋,`j` 次扔鸡蛋的机会,现在尝试在 `1` ~ `n` 层中的任意一层 `x` 扔鸡蛋:
200221

222+
1. 如果鸡蛋没碎,剩下 `i` 个鸡蛋,还有 `j - 1` 次扔鸡蛋的机会,最多可以检测 `dp[i][j - 1]` 层楼层。
223+
2. 如果鸡蛋碎了,剩下 `i - 1` 个鸡蛋,还有 `j - 1` 次扔鸡蛋的机会,最多可以检测 `dp[i - 1][j - 1]` 层楼层。
224+
3. 再加上我们扔鸡蛋的第 `x` 层,`i` 个鸡蛋,`j` 次扔鸡蛋的机会最多可以检测 `dp[i][j - 1] + dp[i - 1][j - 1] + 1` 层。
225+
226+
则状态转移方程为:$dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1] + 1$。
227+
228+
###### 4. 初始条件
229+
230+
- 当鸡蛋数为 `1` 时,只有 `1` 次扔鸡蛋的机会时,最多可以检测 `1` 层,即 `dp[1][1] = 1`
231+
232+
###### 5. 最终结果
233+
234+
根据我们之前定义的状态,`dp[i][j]` 表示为:一共有 `i` 个鸡蛋,最多扔 `j` 次鸡蛋(碎没碎都算 `1` 次)的条件下,最多可以检测的楼层个数。则我们需要从满足 `i == k` 并且 `dp[i][j] >= n`(即 `k` 个鸡蛋,`j` 次扔鸡蛋,一共检测出 `n` 层楼)的情况中,找出最小的 ` j`,将其返回。
201235

202236
### 思路 3:代码
203237

204238
```Python
205239
class Solution:
206240
def superEggDrop(self, k: int, n: int) -> int:
207-
dp = [[i for _ in range(k + 1)] for i in range(n + 1)]
241+
dp = [[0 for _ in range(n + 1)] for i in range(k + 1)]
208242
dp[1][1] = 1
209243

210-
for i in range(1, n + 1):
211-
for j in range(1, k + 1):
212-
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] + 1
213-
if j == k and dp[i][j] >= n:
214-
return i
244+
for i in range(1, k + 1):
245+
for j in range(1, n + 1):
246+
dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1] + 1
247+
if i == k and dp[i][j] >= n:
248+
return j
215249
return n
216250
```
217251

@@ -224,3 +258,4 @@ class Solution:
224258

225259
- 【题解】[题目理解 + 基本解法 + 进阶解法 - 鸡蛋掉落 - 力扣](https://leetcode.cn/problems/super-egg-drop/solution/ji-ben-dong-tai-gui-hua-jie-fa-by-labuladong/)
226260
- 【题解】[动态规划(只解释官方题解方法一)(Java) - 鸡蛋掉落 - 力扣](https://leetcode.cn/problems/super-egg-drop/solution/dong-tai-gui-hua-zhi-jie-shi-guan-fang-ti-jie-fang/)
261+
- 【题解】[动态规划 & 记忆化搜索 2000ms -> 32ms 的过程 - 鸡蛋掉落 - 力扣](https://leetcode.cn/problems/super-egg-drop/solution/python-dong-tai-gui-hua-ji-yi-hua-sou-su-hnj9/)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /