写目录
- 一个鸡蛋
- 两个鸡蛋
- K个鸡蛋
今天面试官问了我这个扔鸡蛋问题,以前学过,但是面试的时候想不起来了,应该是直接寄了,接下来总结一下这个问题的动态规划做法.
问题:有一个N层高的楼,现在给你若干个鸡蛋,要求你用最少的次数测试出第一个鸡蛋会碎的楼层
一个鸡蛋
只需要从第一层开始一层一层扔就行了,最坏情况需要扔N次
两个鸡蛋
两个鸡蛋
分析:
当我们在第i层扔鸡蛋时,会有两种情况
- 鸡蛋碎了,那代表碎了,那代表答案肯定在 [1,i-1]这个区间,鸡蛋只剩一个了,所以只能一层一层扔,所以最坏情况就是 i-1 + 1 = i次
- 鸡蛋没碎,那就又回到了对剩下的 n -i 层有两个鸡蛋测试的情况,所以此时最坏情况是 1 + dp[n-i]
所以我们需要取两种情况中次数最坏的情况
代码如下:
class Solution {
public:int twoEggDrop(int n) {if(n<=2)return n;int dp[1001];for(int i=1;i<=n;i++){int mmin=INT_MAX;for(int j=1;j<=i;j++){mmin=min(mmin,max(j,dp[i-j]+1));}dp[i]=mmin;}return dp[n];}
};
K个鸡蛋
K个鸡蛋
这里直接使用力扣网的官方题解:
动态规划法+二分查找
class Solution {
public:unordered_map<int,int> mmap;int dp(int k,int n){if(mmap.find(n*100+k)==mmap.end()){int ans;if(n==0)ans=0;else if(k==1)ans=n;else{int left=1;int right=n;while(left+1<right){int mid=(left+right)>>1;int t1=dp(k-1,mid-1);int t2=dp(k,n-mid);if(t1<t2){left=mid;}else if(t1>t2){right=mid;}else{left=right=mid;}}ans=1+min(max(dp(k-1,left-1),dp(k,n-left)),max(dp(k-1,right-1),dp(k,n-right)));}mmap[100*n+k]=ans;}return mmap[100*n+k];}int superEggDrop(int k, int n) {return dp(k,n);}
};