🐏 给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。
已知存在楼层 f
满足 0 <= f <= n
任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。
每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。
如果鸡蛋碎了,你就不能再次使用它。
如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。
请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?
示例 1:
输入:k = 1, n = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,肯定能得出 f = 0 。
否则,鸡蛋从 2 楼掉落。如果它碎了,肯定能得出 f = 1 。
如果它没碎,那么肯定能得出 f = 2 。
因此,在最坏的情况下我们需要移动 2 次以确定 f 是多少。
示例 2:
输入:k = 2, n = 6
输出:3
解释:
假设鸡蛋从3楼掉落,如果它碎了,目前就剩下一枚鸡蛋,它必须走1、2楼才能判断f是多少,所以f为1+2=3
假设鸡蛋从3楼掉落没碎,目前剩下两枚鸡蛋,可以用一枚鸡蛋从5楼扔下
如果碎了,目前剩下一枚鸡蛋,从4楼扔下 确定 f 的值 f为 1+1+1 = 3
如果没碎,目前剩下两枚鸡蛋,从6楼扔下 ,确定f的值 为 1+1+1 =3
示例 3:
输入:k = 3, n = 14
输出:4
提示:
1 <= k <= 100
1 <= n <= 10的4次方
一开始我看这题直接就懵了… 感觉压根没理解… 后来看了大佬的题解才明白的~
🐓 思路:二分法查找最小值+动态规划
可以根据楼层N的数量,每次取中点楼层 扔鸡蛋,然后判断该鸡蛋是否碎 来获取下面部分的f和上面部分的f值 取最小值
上代码
public static int superEggDrop(int k, int n) {
if(k == 0 || n == 0) {
return 0;
}
int[][] dp = new int[k+1][n+1];
return dp(dp,k,n);
}
public static int dp(int[][] arr , int k , int n ) {
if(k == 1) {
return n;
}
if(n == 0) {
return 0;
}
if(arr[k][n] > 0) {
return arr[k][n];
}
int slow = 1;
int height = n;
int temp = Integer.MAX_VALUE;
while(slow <= height) {
int mid = slow +((height-slow)>>1);
int res1 = dp(arr,k-1,mid-1);
int res2 = dp(arr,k,n-mid);
if(res1 > res2) {
height = mid - 1;
temp = Math.min(temp, res1+1);
}else {
slow = mid + 1;
temp = Math.min(temp, res2+1);
}
}
arr[k][n] = temp;
return arr[k][n];
}