leetcode困难887鸡蛋掉落
Posted qq_40707462
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode困难887鸡蛋掉落相关的知识,希望对你有一定的参考价值。
思路1:递归
N :使用一栋从 1 到 N 共有 N 层楼的建筑
F :满足 0 <= F <= N ,任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破(F 比 N 多一个 0 层)
问题转换:
将问题从: N 个楼层,有 K 个蛋,求最少要扔 T 次,才能保证当 F 无论是 0 <= F <= N 中哪个值,都能测试出来
转变为:有 K 个蛋,扔 T 次,求可以确定 F 的个数,然后得出 N 个楼层
- 1个蛋 T 次机会,或 K 个蛋 1 次机会,只可以确定出 T + 1 个 F(去掉0层,即最多可以确定第 T 楼)
- 其他情况时,递归。【蛋碎了减 1 个,机会减 1 次】 + 【蛋没碎,机会减 1 次】
比如: N = 2 层楼(只需要K(1) 个蛋,扔T(2)次)
在 1 层扔,碎了,F < 1,所以确定 F = 0
在 1 层扔,没碎,但在 2 层扔,碎了, F >= 1 && F < 2,所以确定 F = 1
在 2 层扔,没碎,F >= 2,所以确定 F = 2
比如:K(2) 个蛋,T(3)次机会
- 第一次应当从 3 层仍,最坏情况碎了,剩下 K(1) 个蛋,T(2)次机会,可以判断一二层的情况;
- 第二次从 5 层扔,碎了的话,剩下 K(1) 个蛋,T(1)次机会,也可以判断 T+1=2 个楼层的情况,即三四层情况
- 如果还没碎,剩下 K(2) 个蛋,T(1)次机会,只能从 6 层扔,判断T+1=2 个楼层的情况,即五六楼情况
class Solution {
public int superEggDrop(int k, int n) {
int T=1;
while(calF(k,T)<n+1) T++;
return T;
}
public int calF(int K,int T){
if (T == 1 || K == 1) return T + 1;
return calF(K - 1, T - 1) + calF(K, T - 1);
}
}
优化:动态规划,避免递归重复计算
左边是碎的那段 长度是dp[k][T - 1]
右边是没碎的那段 长度是dp[k-1][T - 1]
因为已经碎了一个了
中间是我选定扔的楼层 是1
class Solution {
public int superEggDrop(int k, int n) {
int[][]dp=new int[k+1][10000];
int T=0;
while(dp[k][T]<n){
T+=1;
for(int i=1;i<=k;i++){
dp[i][T]=1+dp[i-1][T-1]+dp[i][T-1];
}
}
return T;
}
}
再优化:dp[i][T]=1+dp[i-1][T-1]+dp[i][T-1];
里的[T-1]
是相同的,所以可以忽略这一维,如果采用k
倒着从大到小计算 就可以只存一行的dp[k]
直接原地更新dp[k]
不影响后续计算
class Solution {
public int superEggDrop(int k, int n) {
int[]dp=new int[k+1];
int T=0;
while(dp[k]<n){
T+=1;
for(int i=k;i>0;i--){
dp[i]=1+dp[i-1]+dp[i];
}
}
return T;
}
}
以上是关于leetcode困难887鸡蛋掉落的主要内容,如果未能解决你的问题,请参考以下文章