@@ -56,11 +56,10 @@ What is the minimum number of moves that you need to know with certainty what
56
56
57
57
- 给出 ` K ` 个鸡蛋,` N ` 层楼,要求确定安全楼层 ` F ` 需要最小步数 ` t ` 。
58
58
- 这一题是微软的经典面试题。拿到题最容易想到的是二分搜索。但是仔细分析以后会发现单纯的二分是不对的。不断的二分确实能找到最终安全的楼层,但是这里没有考虑到 ` K ` 个鸡蛋。鸡蛋数的限制会导致二分搜索无法找到最终楼层。题目要求要在保证能找到最终安全楼层的情况下,找到最小步数。所以单纯的二分搜索并不能解答这道题。
59
- - 这一题如果按照题意正向考虑,动态规划的状态转移方程是 ` searchTime(K, N) = max( searchTime(K-1, X-1), searchTime(K, N-X) ) ` 。其中 ` X ` 是丢鸡蛋的楼层。随着 ` X ` 从 ` [1,N] ` ,都能计算出一个 ` searchTime ` 的值,在所有这 ` N ` 个值之中,取最小值就是本题的答案了。这个解法可以 AC 这道题。不过这个解法不细展开了。时间复杂度 ` O(k*N^2) ` 。
60
- <p align =' center ' >
61
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_8.png ' >
62
- </p >
63
-
59
+ - 这一题如果按照题意正向考虑,动态规划的状态转移方程是 ` searchTime(K, N) = max( searchTime(K-1, X-1), searchTime(K, N-X) ) ` 。其中 ` X ` 是丢鸡蛋的楼层。随着 ` X ` 从 ` [1,N] ` ,都能计算出一个 ` searchTime ` 的值,在所有这 ` N ` 个值之中,取最小值就是本题的答案了。这个解法可以 AC 这道题。不过这个解法不细展开了。时间复杂度 ` O(k*N^2) ` 。
60
+ {{< katex display >}}
61
+ dp(K,N) = MIN \begin{bmatrix} \, \, MAX(dp(K-1,X-1),dp(K,N-X))\, \, \end{bmatrix} ,1\leqslant x \leqslant N \\
62
+ {{< /katex >}}
64
63
- 换个角度来看这个问题,定义 ` dp[k][m] ` 代表 ` K ` 个鸡蛋,` M ` 次移动能检查的最大楼层。考虑某一步 ` t ` 应该在哪一层丢鸡蛋呢?一个正确的选择是在 ` dp[k-1][t-1] + 1 ` 层丢鸡蛋,结果分两种情况:
65
64
1 . 如果鸡蛋碎了,我们首先排除了该层以上的所有楼层(不管这个楼有多高),而对于剩下的 ` dp[k-1][t-1] ` 层楼,我们一定能用 ` k-1 ` 个鸡蛋在 ` t-1 ` 步内求解。因此这种情况下,我们总共可以求解无限高的楼层。可见,这是一种非常好的情况,但并不总是发生。
66
65
2 . 如果鸡蛋没碎,我们首先排除了该层以下的 ` dp[k-1][t-1] ` 层楼,此时我们还有 ` k ` 个蛋和 ` t-1 ` 步,那么我们去该层以上的楼层继续测得 ` dp[k][t-1] ` 层楼。因此这种情况下,我们总共可以求解 ` dp[k-1][t-1] + 1 + dp[k][t-1] ` 层楼。
@@ -70,43 +69,34 @@ What is the minimum number of moves that you need to know with certainty what
70
69
2 . 如果在更高的楼层丢鸡蛋,假设是第 ` dp[k-1][t-1] + 2 ` 层丢鸡蛋,如果这次鸡蛋碎了,剩下 ` k-1 ` 个鸡蛋和 ` t-1 ` 步只能保证验证 ` dp[k-1][t-1] ` 的楼层,这里还剩** 第** ` dp[k-1][t-1]+ 1 ` 的楼层,不能保证最终一定能找到安全楼层了。
71
70
- 用反证法就能得出每一步都应该在第 ` dp[k-1][t-1] + 1 ` 层丢鸡蛋。
72
71
- 这道题还可以用二分搜索来解答。回到上面分析的状态转移方程:` dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1 ` 。用数学方法来解析这个递推关系。令 ` f(t,k) ` 为 ` t ` 和 ` k ` 的函数,题目所要求能测到最大楼层是 ` N ` 的最小步数,即要求出 ` f(t,k) ≥ N ` 时候的最小 ` t ` 。由状态转移方程可以知道:` f(t,k) = f(t-1,k) + f(t-1,k-1) + 1 ` ,当 ` k = 1 ` 的时候,对应一个鸡蛋的情况,` f(t,1) = t ` ,当 ` t = 1 ` 的时候,对应一步的情况,` f(1,k) = 1 ` 。有状态转移方程得:
73
- <p align =' center ' >
74
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_1.png ' >
75
- </p >
76
-
77
- - 令 ` g(t,k) = f(t,k) - f(t,k-1) ` ,可以得到:
78
-
79
- <p align =' center ' >
80
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_2.png ' >
81
- </p >
82
-
83
- - 可以知道 ` g(t,k) ` 是一个杨辉三角,即二项式系数:
84
-
85
- <p align =' center ' >
86
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_3.png ' >
87
- </p >
88
-
89
- - 利用裂项相消的方法:
90
- <p align =' center ' >
91
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_4.png ' >
92
- </p >
93
-
94
- - 于是可以得到:
95
- <p align =' center ' >
96
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_5.png ' >
97
- </p >
98
-
99
- - 其中:
100
- <p align =' center ' >
101
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_6.png ' >
102
- </p >
103
-
104
- - 于是针对每一项的二项式常数,都可以由前一项乘以一个分数得到下一项。
105
- <p align =' center ' >
106
- <img src =' https://img.halfrost.com/Leetcode/leetcode_887_7.png ' >
107
- </p >
108
-
109
- - 利用二分搜索,不断的二分 ` t ` ,直到逼近找到 ` f(t,k) ≥ N ` 时候最小的 ` t ` 。时间复杂度 ` O(K * log N) ` ,空间复杂度 ` O(1) ` 。
72
+ {{< katex display >}}
73
+ \begin{aligned} f(t,k) &= 1 + f(t-1,k-1) + f(t-1,k) \\ f(t,k-1) &= 1 + f(t-1,k-2) + f(t-1,k-1) \\ \end{aligned}
74
+ {{< /katex >}}
75
+ 令 ` g(t,k) = f(t,k) - f(t,k-1) ` ,可以得到:
76
+ {{< katex display >}}
77
+ g(t,k) = g(t-1,k) + g(t-1,k-1)
78
+ {{< /katex >}}
79
+ 可以知道 ` g(t,k) ` 是一个杨辉三角,即二项式系数:
80
+ {{< katex display >}}
81
+ g(t,k) = \binom{t}{k+1} = C_ {t}^{k+1}
82
+ {{< /katex >}}
83
+ 利用裂项相消的方法:
84
+ {{< katex display >}}
85
+ \begin{aligned} g(t,x) &= f(t,x) - f(t,x-1) \\ g(t,x-1) &= f(t,x-1) - f(t,x-2) \\ g(t,x-2) &= f(t,x-2) - f(t,x-3) \\ \begin{matrix} .\\ .\\ .\\ \end{matrix}\\ g(t,2) &= f(t,2) - f(t,1) \\ g(t,1) &= f(t,1) - f(t,0) \\ \end{aligned}
86
+ {{< /katex >}}
87
+ 于是可以得到:
88
+ {{< katex display >}}
89
+ \begin{aligned} f(t,k) &= \sum_ {1}^{k}g(t,x) = \sum_ {0}^{k} \binom{t}{x} \\ &= C_ {t}^{0} + C_ {t}^{1} + C_ {t}^{2} + ... + C_ {t}^{k} \\ \end{aligned}
90
+ {{< /katex >}}
91
+ 其中:
92
+ {{< katex display >}}
93
+ \begin{aligned} C_ {t}^{k} \cdot \frac{n-k}{k+1} &= C_ {t}^{k+1} \\ C_ {t}^{k} &= C_ {t}^{k-1} \cdot \frac{t-k+1}{k} \\ \end{aligned}
94
+ {{< /katex >}}
95
+ 于是针对每一项的二项式常数,都可以由前一项乘以一个分数得到下一项。
96
+ {{< katex display >}}
97
+ \begin{aligned} C_ {t}^{0} &= 1 \\ C_ {t}^{1} &= C_ {t}^{0} \cdot \frac{t-1+1}{1} \\ C_ {t}^{2} &= C_ {t}^{1} \cdot \frac{t-2+1}{2} \\ C_ {t}^{3} &= C_ {t}^{2} \cdot \frac{t-3+1}{3} \\ \begin{matrix} .\\ .\\ .\\ \end{matrix}\\ C_ {t}^{k} &= C_ {t}^{k-1} \cdot \frac{t-k+1}{k} \\ \end{aligned}
98
+ {{< /katex >}}
99
+ 利用二分搜索,不断的二分 ` t ` ,直到逼近找到 ` f(t,k) ≥ N ` 时候最小的 ` t ` 。时间复杂度 ` O(K * log N) ` ,空间复杂度 ` O(1) ` 。
110
100
111
101
112
102
0 commit comments