Dynamic Programming · 23 of 60
Egg Dropping Problem
With a few eggs and a tall building, find the fewest drops that always tell you the highest floor an egg survives.
- Simple way
- time O(2^k)
room O(k) - Clever way
- time O(n * k^2)
room O(n * k)
The problem, simply
You have n eggs and a building with k floors. There is some floor where eggs start to break: an egg dropped from below it survives, and from it or above it breaks. It might even be that no floor breaks the egg.
An egg that survives can be dropped again. A broken egg is gone. Find the smallest number of drops that is always enough to find that floor, even with the worst luck.
A story to remember it
Picture it
A building with 10 floors and 2 eggs. The first egg is dropped from floors 4, 7, 9 and 10: jumps of 4, 3, 2, 1. As soon as it breaks, the second egg checks the floors in the gap one by one from the bottom. Every case takes at most 4 drops.
- looking now
- checking
Examples
Two eggs, ten floors
- In
n = 2, k = 10- Out
4
The plan in the picture: drop from 4, 7, 9, 10, and use the second egg for the gap. Three drops can only cover 6 floors with 2 eggs.
One egg
- In
n = 1, k = 5- Out
5
With one egg you must try floors 1, 2, 3, 4, 5 in order. If you skip a floor and the egg breaks, you can never check the skipped floor.
The famous puzzle
- In
n = 2, k = 100- Out
14
14 + 13 + 12 + ... + 1 = 105, which is at least 100. 13 drops only reach 91.
Three eggs
- In
n = 3, k = 14- Out
4
4 drops with 3 eggs can check exactly 14 floors.
No floors
- In
n = 5, k = 0- Out
0
There is nothing to find, so no drops are needed.
Way 1: the simple way
Try every floor x for the first drop. Two things can happen:
- The egg breaks. The answer is below
x:x - 1floors left,n - 1eggs. - The egg survives. The answer is above
x:k - xfloors left,neggs.
We must be ready for the worse of the two, so take the max. Then pick the floor x that makes this worst case smallest, so take the min over x. Add 1 for the drop itself.
k == 0ork == 1: returnk. One egg: returnk.- Otherwise return
1 + min over x of max(drops(n - 1, x - 1), drops(n, k - x)).
Calls for 2 eggs and 3 floors. A circle e,f means e eggs and f floors still unknown. From each try, branch B is the egg breaking (one egg fewer, floors below) and branch S is the egg surviving (same eggs, floors above). Faded circles are questions already asked. Double rings are answered right away.
- seen
class Solution {
public int eggDrop(int n, int k) {
if (k == 0 || k == 1) return k; // 0 or 1 floor
if (n == 1) return k; // one egg: go floor by floor
int best = Integer.MAX_VALUE;
for (int x = 1; x <= k; x++) {
int breaks = eggDrop(n - 1, x - 1); // look below with one egg fewer
int survives = eggDrop(n, k - x); // look above with the same eggs
int worst = 1 + Math.max(breaks, survives);
best = Math.min(best, worst); // pick the floor with the best worst case
}
return best;
}
}How long it takes: every call loops over all floors and calls itself twice for each, so it blows up exponentially, around O(2^k). Extra room: the chain of calls, O(k).
Way 2: the clever way
There are only n * k different questions "e eggs, f floors". Fill them in a table dp[e][f], starting with 1 egg, then 2, and so on, and for each egg count with few floors first.
dp[1][f] = fanddp[e][0] = 0,dp[e][1] = 1.- For
efrom 2 ton, forffrom 2 tok:dp[e][f] = 1 + min over x of max(dp[e-1][x-1], dp[e][f-x]). - The answer is
dp[n][k].
The two boxes read for a try at floor x are one row up (fewer eggs) and earlier in the same row (fewer floors). Both are ready.
Fill the table for 2 eggs and up to 6 floors
01 / 08
With 1 egg you cannot risk skipping floors. Drop from floor 1, then 2, then 3, until it breaks. So f floors take f drops in the worst case.
- looking now
- checking
- answer
- path
- just added
- ignored
class Solution {
public int eggDrop(int n, int k) {
int[][] dp = new int[n + 1][k + 1]; // dp[e][f]: drops for e eggs, f floors
for (int e = 1; e <= n; e++) {
dp[e][0] = 0; // no floors
dp[e][1] = 1; // one floor: one drop
}
for (int f = 1; f <= k; f++) dp[1][f] = f; // one egg: floor by floor
for (int e = 2; e <= n; e++) {
for (int f = 2; f <= k; f++) {
dp[e][f] = Integer.MAX_VALUE;
for (int x = 1; x <= f; x++) {
int worst = 1 + Math.max(dp[e - 1][x - 1], dp[e][f - x]);
dp[e][f] = Math.min(dp[e][f], worst);
}
}
}
return dp[n][k];
}
}How long it takes: n * k boxes, each trying up to k floors, O(n * k^2). Extra room: the table, O(n * k).
Way 3: flip the question
Top companies and quant firms often push further. Instead of "how many drops for k floors?", ask "with m drops and e eggs, how many floors can I fully check?" Call it reach(m, e).
Drop once. If the egg breaks, the floors below must be checkable with m - 1 drops and e - 1 eggs. If it survives, the floors above must be checkable with m - 1 drops and e eggs. Plus the floor you dropped from:
reach(m, e) = reach(m - 1, e - 1) + reach(m - 1, e) + 1
Grow m until reach(m, n) is at least k. That m is the answer.
How many floors can 2 eggs check?
01 / 05
Flip the question: with m drops and e eggs, how many floors can we fully check? With 0 drops, 0 floors. We stop at the first row that reaches 10.
- answer
- just added
class Solution {
public int eggDrop(int n, int k) {
int[] reach = new int[n + 1]; // reach[e]: floors checkable with e eggs
int moves = 0;
while (reach[n] < k) {
moves++;
// go from many eggs to few, so reach[e - 1] is still the old value
for (int e = n; e >= 1; e--) {
reach[e] = reach[e - 1] + reach[e] + 1;
}
}
return moves;
}
}How long it takes: n updates per drop, and the number of drops m is the answer, so O(n * m). With many eggs m is about log2(k). Extra room: O(n).
Watch out for
- One egg means floor by floor. Do not binary search with one egg: if it breaks on the first try you lose.
- Do not forget the
+ 1for the drop you just made. - In Way 3, update
reachfrom the most eggs down to 1 egg, orreach[e - 1]is already the new value.
What interviewers ask next
- Speed up Way 2? For fixed
eandf,dp[e-1][x-1]grows withxanddp[e][f-x]shrinks, so binary search the crossing point:O(n * k * log k). - Why is 2 eggs and 100 floors 14? With
mdrops, 2 eggs reachm + (m-1) + ... + 1 = m(m+1)/2floors. The smallestmwithm(m+1)/2 >= 100is 14. - Is there a formula for
reach?reach(m, e) = C(m, 1) + C(m, 2) + ... + C(m, e), a sum of binomial coefficients. - Unlimited eggs? Then it is plain binary search:
ceil(log2(k + 1))drops.
Remember this
Grown-up words: "worst luck" is the worst case, min of max is a minimax choice, the chart is a 2D DP table over eggs and floors, and flipping the question means changing the DP state from floors to moves.