Taro Logo

Super Egg Drop

Hard
Asked by:
Profile picture
Profile picture
Profile picture
Profile picture
+2
More companies
Profile picture
Profile picture
91 views
Topics:
Dynamic Programming

You are given k identical eggs and you have access to a building with n floors labeled from 1 to n.

You know that there exists a floor f where 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 unbroken egg and drop it from any floor x (where 1 <= x <= n). If the egg breaks, you can no longer use it. However, if the egg does not break, you may reuse it in future moves.

Return the minimum number of moves that you need to determine with certainty what the value of f is.

Example 1:

Input: k = 1, n = 2
Output: 2
Explanation: 
Drop the egg from floor 1. If it breaks, we know that f = 0.
Otherwise, drop the egg from floor 2. If it breaks, we know that f = 1.
If it does not break, then we know f = 2.
Hence, we need at minimum 2 moves to determine with certainty what the value of f is.

Example 2:

Input: k = 2, n = 6
Output: 3

Example 3:

Input: k = 3, n = 14
Output: 4

Constraints:

  • 1 <= k <= 100
  • 1 <= n <= 104

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. What are the maximum values for the number of eggs (K) and the number of floors (N)?
  2. If it's impossible to determine the critical floor with the given number of eggs and floors, what should I return?
  3. Are the floors numbered sequentially from 1 to N, or is there a different numbering system?
  4. Is it safe to assume that both K and N will always be positive integers, never zero or negative?
  5. If an egg breaks on a floor, does it mean it will also break on all floors above it, and if an egg doesn't break, does it mean it won't break on any floors below it?

Brute Force Solution

Approach

Imagine you're trying to find the highest floor in a building from which an egg won't break, given a certain number of eggs and floors. The brute force method is like actually trying out every single possibility of egg drops to figure it out. We will go floor by floor.

Here's how the algorithm would work step-by-step:

  1. Start by picking a floor to drop the first egg from.
  2. If the egg breaks, you now know the target floor is below this one. You'll need to try every floor below, one by one, using your remaining eggs.
  3. If the egg doesn't break, you know the target floor is at or above this one. You'll need to repeat the process, dropping an egg from a higher floor.
  4. Keep track of the maximum number of drops it takes in the worst-case scenario, depending on which floor you initially picked.
  5. Repeat this whole process for every possible starting floor.
  6. Finally, choose the strategy (the starting floor) that gives you the smallest maximum number of drops in the worst case.

Code Implementation

def super_egg_drop_brute_force(number_of_eggs, number_of_floors):
    def solve_egg_drop(eggs_remaining, current_floor_count):
        if current_floor_count == 0:
            return 0
        if eggs_remaining == 1:
            return current_floor_count

        minimum_drops_needed = float('inf')

        for floor_to_try in range(1, current_floor_count + 1):
            # We take the max because we want to account for the worst case
            worst_case_drops = max(
                solve_egg_drop(eggs_remaining - 1, floor_to_try - 1),
                solve_egg_drop(eggs_remaining, current_floor_count - floor_to_try)
            ) + 1

            # Find starting floor with minimal worst case drops
            minimum_drops_needed = min(minimum_drops_needed, worst_case_drops)

        return minimum_drops_needed

    # Kick off the recursive process
    return solve_egg_drop(number_of_eggs, number_of_floors)

Big(O) Analysis

Time Complexity
O(n²)The algorithm iterates through each of the n floors as a potential starting point for the first egg drop. For each starting floor, in the worst-case scenario, it may need to test all the floors either above or below the chosen floor, which is another loop that can go up to n times. Thus, we are doing n operations, n times. Therefore, the total number of operations approximates n * n, simplifying to O(n²).
Space Complexity
O(1)The described brute force approach doesn't explicitly create any auxiliary data structures like arrays, hash maps, or lists to store intermediate results or track visited floors. The algorithm primarily involves iterative calculations and comparisons. The space used is dominated by a few variables to store the current floor, number of drops, and minimum drops, which remains constant regardless of the number of floors or eggs. Therefore, the auxiliary space complexity is O(1).

Optimal Solution

Approach

The key to efficiently solving this problem is to reframe the question. Instead of focusing on minimizing the number of attempts to find the breaking point, we focus on finding out how many floors we can cover with a given number of eggs and attempts.

Here's how the algorithm would work step-by-step:

  1. Think about the problem in reverse: instead of figuring out the fewest drops, figure out the maximum number of floors you can check with a certain number of eggs and drops.
  2. Imagine you have a certain number of eggs and drops. If the egg breaks when you drop it, you have one less egg and one less drop to check the floors below. If the egg doesn't break, you still have the same number of eggs but one less drop to check the floors above.
  3. The maximum number of floors you can check is the sum of the floors you can check if the egg breaks plus the floors you can check if the egg doesn't break, plus the floor you dropped the egg on.
  4. Use this relationship to build up a table showing how many floors you can check with different numbers of eggs and drops.
  5. Continue building the table until you find a combination of eggs and drops that allows you to check at least as many floors as you have in the problem. The number of drops in that combination is your answer.

Code Implementation

def superEggDrop(number_of_eggs, number_of_floors):    maximum_attempts = 0
    dp_table = [[0] * (number_of_eggs + 1) for _ in range(number_of_floors + 1)]
    
    while dp_table[maximum_attempts][number_of_eggs] < number_of_floors:
        maximum_attempts += 1
        for egg_count in range(1, number_of_eggs + 1):
            # Dynamic programming to find floors covered.
            dp_table[maximum_attempts][egg_count] = dp_table[maximum_attempts - 1][egg_count - 1] + dp_table[maximum_attempts - 1][egg_count] + 1

    # The minimum number of attempts is returned.
    return maximum_attempts

Big(O) Analysis

Time Complexity
O(K*N)The algorithm uses dynamic programming to build a table where the rows represent the number of eggs (K) and the columns represent the number of moves (N). The algorithm iterates through all possible combinations of eggs and moves to calculate the maximum number of floors that can be checked. Thus, we iterate through the outer loop K times, and the inner loop N times. Therefore, the time complexity is directly proportional to the product of K and N, which results in O(K*N).
Space Complexity
O(K * D)The algorithm constructs a table to store the maximum number of floors that can be checked with a certain number of eggs (K) and drops (D), where K is the number of eggs and D is the number of drops. The table has dimensions K x D, meaning it stores a value for each combination of eggs and drops up to the given limits. This table directly contributes to the auxiliary space required. Therefore, the space complexity is proportional to the product of the number of eggs and the maximum number of drops, resulting in O(K * D).

Edge Cases

K = 0 (No eggs)
How to Handle:
If there are no eggs, it's impossible to determine the critical floor, return 0.
N = 0 (No floors)
How to Handle:
If there are no floors, no drops are needed, return 0.
K = 1 (One egg)
How to Handle:
With one egg, the only strategy is to test each floor sequentially, worst-case N drops are needed.
N = 1 (One floor)
How to Handle:
With one floor, only one drop is needed regardless of the number of eggs, return 1.
Large N and K values that cause integer overflow in calculations
How to Handle:
Use a data type with a larger range (e.g., long) or use dynamic programming with memoization to reduce calculation redundancy to avoid overflow.
N is very large, and K is a 'small' number (e.g. N=10000, K=2). Standard DP would be slow.
How to Handle:
Binary search approach can be utilized to optimize the number of drops needed, improving performance significantly.
When using recursion, the call stack may overflow for very large N or K values.
How to Handle:
Use dynamic programming instead of recursion to avoid stack overflow issues, storing already computed solutions to reuse.
Extreme boundary values of N and K exceeding memory limits.
How to Handle:
Optimize space complexity by only storing necessary rows/columns in the dynamic programming table, releasing memory when it is no longer needed.