K-Crystal Balls Problem: Drops, Floors, and the Optimal DP
The K-crystal balls problem — better known in the algorithms canon as the egg-drop problem — asks for the worst-case-optimal number of test drops needed to find a breaking-floor threshold when each broken test resource is permanently consumed. The two-egg case has a clean closed form
Problem Definition
Given
The objective is the worst-case number of drops over an adversarially chosen
state : (k, n) = (eggs remaining, floors still in scope)action : pick a floor x in [1..n], drop an eggoutcome : break -> (k-1, x-1) below, scope = floors below x hold -> (k, n-x) above, scope = floors above xgoal : minimize the maximum drops to identify f*The classic instance —
Note
The literature calls these eggs by convention. “Crystal balls” is the Frontend Masters / interview rebrand of the same model. Treat the two terms as synonyms.
Why Binary Search Fails
Binary search is optimal when each probe is non-destructive — the response narrows the search space symmetrically and you can keep probing. The egg-drop problem breaks that symmetry: a break both narrows the space and removes one of your only test resources.
Consider
- If it survives: 1 egg consumed mentally, 50 floors remain, 2 eggs left — you can recurse.
- If it breaks: 1 egg gone, 49 floors remain, only 1 egg left — you are now forced into a linear scan of floors 1..49. Worst case:
drops.
Pure binary search gives
The asymmetry generalizes: at any state
The Two-Egg Case
The
Setting up the recurrence
Let
- Egg #1 breaks at
. Egg #2 must linearly scan floors to identify . Worst case: drops. - Egg #1 holds at
. Floor is somewhere in . We are now in state and the next drop is some floor with — because if it broke there, egg #2 would scan a window of size and the total would be , which must stay to keep our worst case bounded by .
Continuing inductively, the optimal first-egg drops are at floors
The largest reachable floor after
We need this sum to cover all
Solving the quadratic:
For
Why a fixed jump is not optimal
A common first attempt is “jump by
The improvement comes from spending later drops on smaller windows: by the time egg #1 has survived
Decision tree
Concrete trace
For
Naive Dynamic Programming
For arbitrary
Let
with base cases
function minDropsNaive(k: number, n: number): number { const dp: number[][] = Array.from({ length: k + 1 }, () => new Array(n + 1).fill(0) ) for (let i = 1; i <= n; i++) dp[1][i] = i for (let e = 2; e <= k; e++) { for (let f = 1; f <= n; f++) { let best = Infinity for (let x = 1; x <= f; x++) { const worst = 1 + Math.max(dp[e - 1][x - 1], dp[e][f - x]) if (worst < best) best = worst } dp[e][f] = best } } return dp[k][n]}The inner loop scans all candidate floors
The Optimal Flip: Drops -> Floors
Instead of asking “given
Given
eggs and drops, what is the maximum number of floors that can be guaranteed-resolved?
Once we have
Recurrence
Suppose we have
- If the egg breaks, we have
eggs and drops; we can resolve floors below the test floor. - If the egg holds, we have
eggs and drops; we can resolve floors above the test floor. - The test floor itself contributes 1.
So
with
This is the recurrence proved in the Brilliant: Egg Dropping wiki and used by the canonical
Closed form: a binomial sum
Unrolling the recurrence yields
Inductive proof sketch. Base case
For
Floors-covered growth
Each added egg unlocks a new binomial term and accelerates coverage. The numbers below are
| 4 | 4 | 10 | 14 | 15 |
| 7 | 7 | 28 | 63 | 98 |
| 10 | 10 | 55 | 175 | 385 |
| 13 | 13 | 91 | 377 | 1092 |
| 14 | 14 | 105 | 469 | 1470 |
By
Algorithms and Complexity
| Approach | Time | Space | Notes |
|---|---|---|---|
| Pure recursion, no memo | exponential | Pedagogical only. | |
| DP on |
Direct from the original recurrence; works but slow. | ||
| DP with binary search on the inner |
Uses monotonicity of |
||
| Flipped DP on |
Fill columns of |
||
| Binomial sum + binary search on |
Canonical LeetCode 887 solution; uses the closed form above. |
The
Worked Examples
k = 2, N = 100
Closed form:
k = 3, N = 100
We need the smallest
| 7 | 7 | 21 | 35 | 63 |
| 8 | 8 | 28 | 56 | 92 |
| 9 | 9 | 36 | 84 | 129 |
So
k = 7, N = 100
Implementation
// Closed-form first drop for k = 2, N floors.function firstDropTwoEggs(n: number): number { return Math.ceil((-1 + Math.sqrt(1 + 8 * n)) / 2)}// Run the optimal k = 2 plan against a sorted boolean array of length n.// Returns the index of the threshold floor, or -1 if none.function twoEggThreshold(floors: boolean[]): number { const n = floors.length let step = firstDropTwoEggs(n) let pos = step - 1 // 0-indexed let lastSafe = -1 while (pos < n) { if (floors[pos]) { for (let i = lastSafe + 1; i < pos; i++) { if (floors[i]) return i } return pos } lastSafe = pos step -= 1 if (step <= 0) break pos += step } return -1}// O(k * log N) minimum drops for k eggs and N floors.// Binary-searches the smallest m with sum_{i=1..k} C(m, i) >= n.function minDrops(k: number, n: number): number { if (n === 0) return 0 if (k === 0) return Infinity if (k === 1) return n const floorsCoveredCapped = (m: number): number => { let sum = 0 let term = 1 for (let i = 1; i <= k; i++) { term = (term * (m - i + 1)) / i sum += term if (sum >= n) return n } return sum } let lo = 1 let hi = n while (lo < hi) { const mid = (lo + hi) >> 1 if (floorsCoveredCapped(mid) >= n) hi = mid else lo = mid + 1 } return lo}Tip
For very large BigInt arithmetic to avoid loss of precision in the partial sum.
Edge Cases
| Condition | Behavior |
|---|---|
No probes possible; the threshold cannot be identified. Return Infinity. |
|
| Linear scan only. Worst case = |
|
| Trivially 0 drops. | |
| One drop settles the threshold. | |
| Binary search saturates the bound; extra eggs are unused. | |
| Floating-point drift | Use BigInt or the capped running product for |
Real-World Applications
The egg-drop model maps cleanly onto any threshold-detection problem where a failed test is more expensive than a successful one. Read each application carefully — the literal “broken egg” interpretation is rare.
Reliability and destructive testing
Find the load, voltage, or temperature at which a system fails, with a strict budget of destructive runs (hardware burnt, customer-visible incident triggered, account locked out). Each destructive trial is genuinely consumed; the egg-drop model applies one-to-one and the
Path MTU discovery (loose analogy)
Find the largest packet a path will accept without fragmentation. A probe larger than the path MTU is dropped — like a ball breaking — but it can be retried, so the resource is not strictly consumed. The cost asymmetry (a failed probe burns an RTT plus possible retransmission) still motivates a similar bias toward bigger jumps early. Real implementations of PMTUD (RFC 1191) and Packetization Layer PMTUD (RFC 4821) explicitly avoid pure binary search and use plateau tables of common MTUs because of this asymmetry.
Software version bisection (loose analogy)
git bisect is binary search — each test is non-destructive, so the egg-drop model does not apply. The model becomes relevant only when builds themselves are expensive and parallel: with
Database tuning and capacity probing
Find the selectivity threshold at which an index becomes beneficial, or the throughput at which p99 latency falls off a cliff, with a fixed budget of benchmark runs. Each benchmark consumes wall-clock time and possibly disrupts neighboring tenants. With a fixed test budget, the
Practical Takeaways
- Re-frame “minimum drops for
floors” as “maximum floors for drops” — the DP becomes one-line and the closed form falls out. - For
, memorize and the decreasing-step plan starting at . - For general
, prefer the binomial-sum search over any DP — it is shorter, faster, and numerically stable with capped accumulation. - The egg budget saturates at
. Beyond that, binary search is optimal and extra eggs are dead weight. - The model only literally applies when a failed test is really consumed; for “expensive but repeatable” tests it is a useful upper bound, not a tight one.
References
- Brilliant Math & Science Wiki — Egg Dropping. Recurrence, binomial closed form, and the
derivation in full. - GeeksforGeeks — Eggs Dropping Puzzle (Binomial Coefficient + Binary Search). Explicit
algorithm and implementation. - GeeksforGeeks — Egg Dropping Puzzle | DP-11.
DP, memoization, and the tabulation flip. - LeetCode 887 — Super Egg Drop. Canonical formal write-up for the general
case. - LeetCode 1884 — Egg Drop With 2 Eggs and N Floors. The
instance most readers recognize. - Spencer Mortensen — The Egg Problem. Clean derivation of
. - MIT OCW 6.S095 — Please Do Break the Crystal. Programming for the Puzzled (IAP 2018), Puzzle 4.
- Cao, Chen, Miller (2025) — Egg Drop Problems: They Are All They Are Cracked Up To Be! Modern proof of
and higher-dimensional generalizations. - RFC 1191 — Path MTU Discovery and RFC 4821 — Packetization Layer PMTUD. Why real PMTUD uses plateau tables instead of pure binary or jump search.
- Frontend Masters — Two Crystal Balls Problem. ThePrimeagen’s walkthrough of the
case.