Problem
You are given K
eggs, and you have access to a building with N
floors from 1
to N
.
Each egg is identical in function, and if an egg breaks, you cannot drop it again.
You know that there exists a floor F
with 0 <= F <= N
such that any egg dropped at a floor higher than F
will break, and any egg dropped at or below floor F
will not break.
Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X
(with 1 <= X <= N
).
Your goal is to know with certainty what the value of F
is.
What is the minimum number of moves that you need to know with certainty what F
is, regardless of the initial value of F
?
Example 1:
Input: K = 1, N = 2 Output: 2 Explanation: Drop the egg from floor 1. If it breaks, we know with certainty that F = 0. Otherwise, drop the egg from floor 2. If it breaks, we know with certainty that F = 1. If it didn't break, then we know with certainty F = 2. Hence, we needed 2 moves in the worst case to know what F is with certainty.
Example 2:
Input: K = 2, N = 6 Output: 3
Example 3:
Input: K = 3, N = 14 Output: 4
Note:
1 <= K <= 100
1 <= N <= 10000
Solution 1: Recursion with Memorization (TLE)
dp[k][n] := min number of moves to test n floors with k eggs.
Base cases:
dp[0][n] = 0 # no eggs left.
dp[1][n] = n # one egg, need to test every floor.
Transition:
dp[k][n] = min(1 + max(dp[k][i – 1], dp[k – 1][n – i])) 1 <= i <= n
Time complexity: O(k*n^2)
Space complexity: O(k*n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Author: Huahua // Running time: TLE (69/121 passed) class Solution { public: int superEggDrop(int K, int N) { m_ = vector<vector<int>>(K + 1, vector<int>(N + 1, INT_MIN)); return dp(K, N); } private: // m[i][j] := min moves of i eggs and j floors vector<vector<int>> m_; int dp(int k, int n) { if (k <= 0) return 0; if (k == 1) return n; if (n <= 1) return n; if (m_[k][n] != INT_MIN) return m_[k][n]; int ans = INT_MAX; for (int i = 1; i <= n; ++i) ans = min(ans, 1 + max(dp(k - 1, i - 1), // broken at floor i, need to test i - 1 floors using k - 1 eggs. dp(k, n - i))); // unbroken at floor i, need to test n - i floors using k eggs. return m_[k][n] = ans; } }; |
Solution 2: Solution 1 + Binary Search
Time complexity: O(k*n*logn)
Space complexity: O(k*n)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// Author: Huahua // Running time: 40 ms class Solution { public: int superEggDrop(int K, int N) { m_ = vector<vector<int>>(K + 1, vector<int>(N + 1, INT_MIN)); return dp(K, N); } private: // m[i][j] := min moves of i eggs and j floors vector<vector<int>> m_; int dp(int k, int n) { if (k <= 0) return 0; if (k == 1) return n; if (n <= 1) return n; if (m_[k][n] != INT_MIN) return m_[k][n]; // broken[i] = dp(k - 1, i - 1) is incresing with i. // unbroken[i] = dp(k, n - i) is decresing with i. // dp[k][n] = 1 + min(max(broken[i], unbroken[i])), 1 <= i <= n // find the smallest i such that broken[i] >= unbroken[i], // which minimizes max(broken[i], unbroken[i]). int l = 1; int r = n + 1; while (l < r) { int m = l + (r - l) / 2; int broken = dp(k - 1, m - 1); int unbroken = dp(k, n - m); if (broken >= unbroken) r = m; else l = m + 1; } return m_[k][n] = 1 + dp(k - 1, l - 1); } }; |
请尊重作者的劳动成果,转载请注明出处!花花保留对文章/视频的所有权利。
如果您喜欢这篇文章/视频,欢迎您捐赠花花。
If you like my articles / videos, donations are welcome.
Be First to Comment