Skip to content

Commit 366254d

Browse files
committed
feat: add solutions to lc problem: No.0887
No.0887.Super Egg Drop
1 parent d327511 commit 366254d

File tree

7 files changed

+787
-15
lines changed

7 files changed

+787
-15
lines changed

solution/0800-0899/0887.Super Egg Drop/README.md

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,358 @@
5454

5555
<!-- 这里可写通用的实现逻辑 -->
5656

57+
**方法一:记忆化搜索 + 二分查找**
58+
59+
我们设计一个函数 $dfs(i, j)$,表示有 $i$ 层楼以及 $j$ 个鸡蛋时,确定 $f$ 值的最小操作次数,那么答案就是 $dfs(n, k)$。
60+
61+
函数 $dfs(i, j)$ 的执行逻辑如下:
62+
63+
如果 $i \lt 1$,说明楼层已经小于等于 $0$,此时返回 $0$;
64+
65+
如果 $j = 1$,说明只有一个鸡蛋,那么只能从第一层开始一层一层试,最坏情况下需要试 $i$ 次,此时返回 $i$;
66+
67+
否则,我们考虑枚举第一个鸡蛋从第 $x$ 层扔下的情况,其中 $1 \le x \le i$。如果鸡蛋在第 $x$ 层扔下时碎了,说明 $f \lt x$,此时我们接下来需要在 $x - 1$ 层下方以及剩下的 $j - 1$ 个鸡蛋确定 $f$ 值,总共需要的最小操作次数为 $dfs(x - 1, j - 1) + 1$ 次;如果鸡蛋在第 $x$ 层扔下时没碎,说明 $f \gt x$,此时我们需要在第 $x + 1$ 层及以上以及剩下的 $j$ 个鸡蛋确定 $f$ 值,总共需要的最小操作次数为 $dfs(i - x, j) + 1$ 次。由于我们要保证最坏情况下操作次数最少,因此 $dfs(i, j) = \min_{1 \le x \le i} \max(dfs(x - 1, j - 1), dfs(i - x, j)) + 1$。
68+
69+
如果按照这样的方式枚举,由于状态数有 $n \times k$,每个状态需要枚举 $n$ 次,那么总时间复杂度达到 $O(n^2 \times k)$,这会超出时间限制,我们考虑如何进行优化。
70+
71+
我们注意到函数 $dfs(x - 1, j - 1)$ 随着 $x$ 的增大而单调递增,而函数 $dfs(i - x, j)$ 随着 $x$ 的增大而单调递减,因此存在一个最优的 $x$ 值使得 $\max(dfs(x - 1, j - 1), dfs(i - x, j))$ 达到最小值。我们可以对 $x$ 进行二分查找,找出这个最优的 $x$ 值。其中 $x$ 是满足 $dfs(x - 1, j - 1) \le dfs(i - x, j)$ 的最大整数。这样我们可以将时间复杂度降低到 $O(n \times k \log n)$。
72+
73+
时间复杂度 $O(n \times k \log n)$,空间复杂度 $O(n \times k)$。其中 $n$ 和 $k$ 分别是楼层数和鸡蛋数。
74+
75+
**方法二:动态规划 + 二分查找**
76+
77+
我们也可以使用动态规划的方法解决这个问题。
78+
79+
我们定义 $f[i][j]$ 表示有 $i$ 层楼以及 $j$ 个鸡蛋时,确定 $f$ 值的最小操作次数,那么答案就是 $f[n][k]$。
80+
81+
状态转移方程为 $f[i][j] = \min_{1 \le x \le i} \max(f[x - 1][j - 1], f[i - x][j]) + 1$。
82+
83+
与方法一类似,我们可以使用二分查找来优化 $x$ 的枚举过程。
84+
85+
时间复杂度 $O(n \times k \log n)$,空间复杂度 $O(n \times k)$。其中 $n$ 和 $k$ 分别是楼层数和鸡蛋数。
86+
5787
<!-- tabs:start -->
5888

5989
### **Python3**
6090

6191
<!-- 这里可写当前语言的特殊实现逻辑 -->
6292

6393
```python
94+
class Solution:
95+
def superEggDrop(self, k: int, n: int) -> int:
96+
@cache
97+
def dfs(i: int, j: int) -> int:
98+
if i < 1:
99+
return 0
100+
if j == 1:
101+
return i
102+
l, r = 1, i
103+
while l < r:
104+
mid = (l + r + 1) >> 1
105+
a = dfs(mid - 1, j - 1)
106+
b = dfs(i - mid, j)
107+
if a <= b:
108+
l = mid
109+
else:
110+
r = mid - 1
111+
return max(dfs(l - 1, j - 1), dfs(i - l, j)) + 1
64112

113+
return dfs(n, k)
114+
```
115+
116+
```python
117+
class Solution:
118+
def superEggDrop(self, k: int, n: int) -> int:
119+
f = [[0] * (k + 1) for _ in range(n + 1)]
120+
for i in range(1, n + 1):
121+
f[i][1] = i
122+
for i in range(1, n + 1):
123+
for j in range(2, k + 1):
124+
l, r = 1, i
125+
while l < r:
126+
mid = (l + r + 1) >> 1
127+
a, b = f[mid - 1][j - 1], f[i - mid][j]
128+
if a <= b:
129+
l = mid
130+
else:
131+
r = mid - 1
132+
f[i][j] = max(f[l - 1][j - 1], f[i - l][j]) + 1
133+
return f[n][k]
65134
```
66135

67136
### **Java**
68137

69138
<!-- 这里可写当前语言的特殊实现逻辑 -->
70139

71140
```java
141+
class Solution {
142+
private int[][] f;
143+
144+
public int superEggDrop(int k, int n) {
145+
f = new int[n + 1][k + 1];
146+
return dfs(n, k);
147+
}
148+
149+
private int dfs(int i, int j) {
150+
if (i < 1) {
151+
return 0;
152+
}
153+
if (j == 1) {
154+
return i;
155+
}
156+
if (f[i][j] != 0) {
157+
return f[i][j];
158+
}
159+
int l = 1, r = i;
160+
while (l < r) {
161+
int mid = (l + r + 1) >> 1;
162+
int a = dfs(mid - 1, j - 1);
163+
int b = dfs(i - mid, j);
164+
if (a <= b) {
165+
l = mid;
166+
} else {
167+
r = mid - 1;
168+
}
169+
}
170+
return f[i][j] = Math.max(dfs(l - 1, j - 1), dfs(i - l, j)) + 1;
171+
}
172+
}
173+
```
174+
175+
```java
176+
class Solution {
177+
public int superEggDrop(int k, int n) {
178+
int[][] f = new int[n + 1][k + 1];
179+
for (int i = 1; i <= n; ++i) {
180+
f[i][1] = i;
181+
}
182+
for (int i = 1; i <= n; ++i) {
183+
for (int j = 2; j <= k; ++j) {
184+
int l = 1, r = i;
185+
while (l < r) {
186+
int mid = (l + r + 1) >> 1;
187+
int a = f[mid - 1][j - 1];
188+
int b = f[i - mid][j];
189+
if (a <= b) {
190+
l = mid;
191+
} else {
192+
r = mid - 1;
193+
}
194+
}
195+
f[i][j] = Math.max(f[l - 1][j - 1], f[i - l][j]) + 1;
196+
}
197+
}
198+
return f[n][k];
199+
}
200+
}
201+
```
202+
203+
### **C++**
204+
205+
```cpp
206+
class Solution {
207+
public:
208+
int superEggDrop(int k, int n) {
209+
int f[n + 1][k + 1];
210+
memset(f, 0, sizeof(f));
211+
function<int(int, int)> dfs = [&](int i, int j) -> int {
212+
if (i < 1) {
213+
return 0;
214+
}
215+
if (j == 1) {
216+
return i;
217+
}
218+
if (f[i][j]) {
219+
return f[i][j];
220+
}
221+
int l = 1, r = i;
222+
while (l < r) {
223+
int mid = (l + r + 1) >> 1;
224+
int a = dfs(mid - 1, j - 1);
225+
int b = dfs(i - mid, j);
226+
if (a <= b) {
227+
l = mid;
228+
} else {
229+
r = mid - 1;
230+
}
231+
}
232+
return f[i][j] = max(dfs(l - 1, j - 1), dfs(i - l, j)) + 1;
233+
};
234+
return dfs(n, k);
235+
}
236+
};
237+
```
238+
239+
```cpp
240+
class Solution {
241+
public:
242+
int superEggDrop(int k, int n) {
243+
int f[n + 1][k + 1];
244+
memset(f, 0, sizeof(f));
245+
for (int i = 1; i <= n; ++i) {
246+
f[i][1] = i;
247+
}
248+
for (int i = 1; i <= n; ++i) {
249+
for (int j = 2; j <= k; ++j) {
250+
int l = 1, r = i;
251+
while (l < r) {
252+
int mid = (l + r + 1) >> 1;
253+
int a = f[mid - 1][j - 1];
254+
int b = f[i - mid][j];
255+
if (a <= b) {
256+
l = mid;
257+
} else {
258+
r = mid - 1;
259+
}
260+
}
261+
f[i][j] = max(f[l - 1][j - 1], f[i - l][j]) + 1;
262+
}
263+
}
264+
return f[n][k];
265+
}
266+
};
267+
```
268+
269+
### **Go**
270+
271+
```go
272+
func superEggDrop(k int, n int) int {
273+
f := make([][]int, n+1)
274+
for i := range f {
275+
f[i] = make([]int, k+1)
276+
}
277+
var dfs func(i, j int) int
278+
dfs = func(i, j int) int {
279+
if i < 1 {
280+
return 0
281+
}
282+
if j == 1 {
283+
return i
284+
}
285+
if f[i][j] != 0 {
286+
return f[i][j]
287+
}
288+
l, r := 1, i
289+
for l < r {
290+
mid := (l + r + 1) >> 1
291+
a, b := dfs(mid-1, j-1), dfs(i-mid, j)
292+
if a <= b {
293+
l = mid
294+
} else {
295+
r = mid - 1
296+
}
297+
}
298+
f[i][j] = max(dfs(l-1, j-1), dfs(i-l, j)) + 1
299+
return f[i][j]
300+
}
301+
return dfs(n, k)
302+
}
303+
304+
func max(a, b int) int {
305+
if a > b {
306+
return a
307+
}
308+
return b
309+
}
310+
```
311+
312+
```go
313+
func superEggDrop(k int, n int) int {
314+
f := make([][]int, n+1)
315+
for i := range f {
316+
f[i] = make([]int, k+1)
317+
}
318+
for i := 1; i <= n; i++ {
319+
f[i][1] = i
320+
}
321+
for i := 1; i <= n; i++ {
322+
for j := 2; j <= k; j++ {
323+
l, r := 1, i
324+
for l < r {
325+
mid := (l + r + 1) >> 1
326+
a, b := f[mid-1][j-1], f[i-mid][j]
327+
if a <= b {
328+
l = mid
329+
} else {
330+
r = mid - 1
331+
}
332+
}
333+
f[i][j] = max(f[l-1][j-1], f[i-l][j]) + 1
334+
}
335+
}
336+
return f[n][k]
337+
}
338+
339+
func max(a, b int) int {
340+
if a > b {
341+
return a
342+
}
343+
return b
344+
}
345+
```
346+
347+
### **TypeScript**
348+
349+
```ts
350+
function superEggDrop(k: number, n: number): number {
351+
const f: number[][] = new Array(n + 1)
352+
.fill(0)
353+
.map(() => new Array(k + 1).fill(0));
354+
const dfs = (i: number, j: number): number => {
355+
if (i < 1) {
356+
return 0;
357+
}
358+
if (j === 1) {
359+
return i;
360+
}
361+
if (f[i][j]) {
362+
return f[i][j];
363+
}
364+
let l = 1;
365+
let r = i;
366+
while (l < r) {
367+
const mid = (l + r + 1) >> 1;
368+
const a = dfs(mid - 1, j - 1);
369+
const b = dfs(i - mid, j);
370+
if (a <= b) {
371+
l = mid;
372+
} else {
373+
r = mid - 1;
374+
}
375+
}
376+
return (f[i][j] = Math.max(dfs(l - 1, j - 1), dfs(i - l, j)) + 1);
377+
};
378+
return dfs(n, k);
379+
}
380+
```
72381

382+
```ts
383+
function superEggDrop(k: number, n: number): number {
384+
const f: number[][] = new Array(n + 1)
385+
.fill(0)
386+
.map(() => new Array(k + 1).fill(0));
387+
for (let i = 1; i <= n; ++i) {
388+
f[i][1] = i;
389+
}
390+
for (let i = 1; i <= n; ++i) {
391+
for (let j = 2; j <= k; ++j) {
392+
let l = 1;
393+
let r = i;
394+
while (l < r) {
395+
const mid = (l + r + 1) >> 1;
396+
const a = f[mid - 1][j - 1];
397+
const b = f[i - mid][j];
398+
if (a <= b) {
399+
l = mid;
400+
} else {
401+
r = mid - 1;
402+
}
403+
}
404+
f[i][j] = Math.max(f[l - 1][j - 1], f[i - l][j]) + 1;
405+
}
406+
}
407+
return f[n][k];
408+
}
73409
```
74410

75411
### **...**

0 commit comments

Comments
 (0)