1884. Egg Drop With 2 Eggs and N Floors & 887. Super Egg Drop (DP)

You are given two 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.

In 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.

This question is a really tricky question, if the egg breaks you cannot use it anymore.  So, if you have only two eggs you had better not use the binary search.

How do we solve this question? We first look at the base case, like if there was only 1 egg and n floor, how many moves do we need? it is n. 

What if there was only 1 floor and we have many eggs? only 1 move. 

If we had many eggs, but there is no floor, we only need 0 moves.

We can try to reduce our problem or transform our problem into a set of subproblems that have the same pattern as the original one.  

 You can see we are downscaling the problem and it will finally reach to our base case.

So, let's set up the DP equation. 

DP[eggs][floor] = min(max(DP[eggs - 1][floor - 1], DP[eggs][n - floor]) + 1), finding all the floor.

class Solution {
public:
    int twoEggDrop(int n) {
        // only two cases the egg breaks and does not break
        //dp[egg][n] = min(dp[egg - 1][i - 1], dp[egg][n - i]) + 1
        vector<vector<int>> dp(3, vector<int>(n + 1, 1e9));
        for(int i = 1; i <= n; i++){
            dp[1][i] = i;
        }
        dp[1][0] = dp[2][0] = 0;
        for(int top = 1; top <= n; top++){
            for(int drop_floor = 1; drop_floor <= top; drop_floor++){
                dp[2][top] = min(dp[2][top], max(dp[1][drop_floor - 1], dp[2][top - drop_floor]) + 1);
            }
        }
        return dp[2][n];
    }
};

However, O(N^2 K) is too brute force, can we reduce the time complexity? 

First, we can look at the value of egg breaks. You would find that if the floor increase, the value of the egg break case would increase because you need to search from the 0 floors to that floor, which costs you n steps. On the other hand, if the egg does not break and the floor increases, the moves you need to try would decrease. 

We can use the binary search to find the best value which is when the value of the breaking case and non-breaking case are the same.

class Solution {
private:
public:
    int superEggDrop(int k, int n) {
        vector<vector<int>> dp(k + 1, vector<int>(n + 1, 1e8));
        for(int i = 0; i <= k; i++){
            dp[i][0] = 0;
        }
        for(int i = 0; i <= n; i++){
            dp[1][i] = i;
        }
        for(int top = 1; top <= n; top++){
            for(int egg = 2; egg <= k; egg++){
                int l = 1, r = top;
                while(l <= r){
                    int mid = (l + r) / 2;
                    int egg_break = dp[egg - 1][mid - 1];
                    int egg_fine = dp[egg][top - mid];
                    dp[egg][top] = min(dp[egg][top], max(egg_break, egg_fine) + 1);
                    if(egg_break > egg_fine){
                        r = mid - 1;
                    }else if(egg_fine > egg_break){
                        l = mid + 1;
                    }else break;
                }
            }
        }
        return dp[k][n];
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>