Given n eggs and k floors, find the minimum number of trials needed in worst case to find the floor below which all floors are safe. A floor is safe if dropping an egg from it does not break the egg. Please see n eggs and k floors. for complete statements
Example
Input : n = 2, k = 10
Output : 4
We first try from 4-th floor. Two cases arise,
(1) If egg breaks, we have one egg left so we
need three more trials.
(2) If egg does not break, we try next from 7-th
floor. Again two cases arise.
We can notice that if we choose 4th floor as first
floor, 7-th as next floor and 9 as next of next floor,
we never exceed more than 4 trials.
Input : n = 2. k = 100
Output : 14
We have discussed the problem for 2 eggs and k floors. We have also discussed a dynamic programming solution to find the solution. The dynamic programming solution is based on below recursive nature of the problem. Let us look at the discussed recursive formula from a different perspective.
How many floors we can cover with x trials?
When we drop an egg, two cases arise.
- If egg breaks, then we are left with x-1 trials and n-1 eggs.
- If egg does not break, then we are left with x-1 trials and n eggs
Let maxFloors(x, n) be the maximum number of floors
that we can cover with x trials and n eggs. From above
two cases, we can write.
maxFloors(x, n) = maxFloors(x-1, n-1) + maxFloors(x-1, n) + 1
For all x >= 1 and n >= 1
Base cases :
We can't cover any floor with 0 trials or 0 eggs
maxFloors(0, n) = 0
maxFloors(x, 0) = 0
Since we need to cover k floors,
maxFloors(x, n) >= k ----------(1)
The above recurrence simplifies to following,
Refer this for proof.
maxFloors(x, n) = ∑xCi
1 <= i <= n ----------(2)
Here C represents Binomial Coefficient.
From above two equations, we can say.
∑xCj >= k
1 <= i <= n
Basically we need to find minimum value of x
that satisfies above inequality. We can find
such x using Binary Search.
C++
#include <bits/stdc++.h>
using namespace std;
int binomialCoeff( int x, int n, int k)
{
int sum = 0, term = 1;
for ( int i = 1; i <= n; ++i) {
term *= x - i + 1;
term /= i;
sum += term;
if (sum > k)
return sum;
}
return sum;
}
int minTrials( int n, int k)
{
int low = 1, high = k;
while (low <= high) {
int mid = (low + high) / 2;
if (binomialCoeff(mid, n, k) < k)
low = mid + 1;
else
high = mid;
}
return low;
}
int main()
{
cout << minTrials(2, 10);
return 0;
}
|
Java
class Geeks {
static int binomialCoeff( int x, int n, int k)
{
int sum = 0 , term = 1 ;
for ( int i = 1 ; i <= n && sum < k; ++i) {
term *= x - i + 1 ;
term /= i;
sum += term;
}
return sum;
}
static int minTrials( int n, int k)
{
int low = 1 , high = k;
while (low <= high) {
int mid = (low + high) / 2 ;
if (binomialCoeff(mid, n, k) < k)
low = mid + 1 ;
else
high = mid;
}
return low;
}
public static void main(String args[])
{
System.out.println(minTrials( 2 , 10 ));
}
}
|
Python3
def binomialCoeff(x, n, k):
sum = 0
term = 1
i = 1
while (i < = n and sum < k):
term * = x - i + 1
term / = i
sum + = term
i + = 1
return sum
def minTrials(n, k):
low = 1
high = k
while (low < = high):
mid = (low + high) / / 2
if (binomialCoeff(mid, n, k) < k):
low = mid + 1
else :
high = mid
return low
print (minTrials( 2 , 10 ))
|
C#
using System;
class Geeks
{
static int binomialCoeff( int x, int n, int k)
{
int sum = 0, term = 1;
for ( int i = 1; i <= n && sum < k; ++i) {
term *= x - i + 1;
term /= i;
sum += term;
}
return sum;
}
static int minTrials( int n, int k)
{
int low = 1, high = k;
while (low <= high) {
int mid = (low + high) / 2;
if (binomialCoeff(mid, n, k) < k)
low = mid + 1;
else
high = mid;
}
return low;
}
public static void Main()
{
Console.WriteLine(minTrials(2, 10));
}
}
|
Javascript
<script>
function binomialCoeff(x, n, k)
{
var sum = 0, term = 1;
for ( var i = 1; i <= n && sum < k; ++i)
{
term *= x - i + 1;
term /= i;
sum += term;
}
return sum;
}
function minTrials(n, k)
{
var low = 1, high = k;
while (low < high)
{
var mid = parseInt((low + high) / 2);
if (binomialCoeff(mid, n, k) < k)
low = mid + 1;
else
high = mid;
}
return low;
}
document.write(minTrials(2, 10));
</script>
|
Time Complexity : O(n Log k)
Auxiliary Space: O(1)
Another Approach:
The approach with O(n * k^2) has been discussed before, where dp[n][k] = 1 + max(dp[n – 1][i – 1], dp[n][k – i]) for i in 1…k. You checked all the possibilities in that approach.
Consider the problem in a different way:
dp[m][x] means that, given x eggs and m moves,
what is the maximum number of floors that can be checked
The dp equation is: dp[m][x] = 1 + dp[m - 1][x - 1] + dp[m - 1][x],
which means we take 1 move to a floor.
If egg breaks, then we can check dp[m - 1][x - 1] floors.
If egg doesn't break, then we can check dp[m - 1][x] floors.
C++
#include <bits/stdc++.h>
using namespace std;
int minTrials( int n, int k)
{
vector<vector< int > > dp(k + 1, vector< int >(n + 1, 0));
int m = 0;
while (dp[m][n] < k) {
m++;
for ( int x = 1; x <= n; x++) {
dp[m][x] = 1 + dp[m - 1][x - 1] + dp[m - 1][x];
}
}
return m;
}
int main()
{
cout << minTrials(2, 10);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int minTrials( int n, int k)
{
int dp[][] = new int [k + 1 ][n + 1 ];
int m = 0 ;
while (dp[m][n] < k) {
m++;
for ( int x = 1 ; x <= n; x++)
dp[m][x] = 1 + dp[m - 1 ][x - 1 ]
+ dp[m - 1 ][x];
}
return m;
}
public static void main(String[] args)
{
System.out.println(minTrials( 2 , 10 ));
}
}
|
C#
using System;
class GFG {
static int minTrials( int n, int k)
{
int [, ] dp = new int [k + 1, n + 1];
int m = 0;
while (dp[m, n] < k) {
m++;
for ( int x = 1; x <= n; x++) {
dp[m, x]
= 1 + dp[m - 1, x - 1] + dp[m - 1, x];
}
}
return m;
}
static void Main()
{
Console.Write(minTrials(2, 10));
}
}
|
Javascript
function minTrials( n, k)
{
let dp = new Array(k+1);
for (let i=0;i<=k;i++)
dp[i] = new Array(n+1);
for (let i=0;i<=k;i++)
for (let j=0;j<=n;j++)
dp[i][j]=0;
let m = 0;
while (dp[m][n] < k) {
m++;
for (let x = 1; x <= n; x++) {
dp[m][x] = 1 + dp[m - 1][x - 1] + dp[m - 1][x];
}
}
return m;
}
console.log(minTrials(2, 10));
|
Python3
def minTrials(n, k):
dp = [[ 0 for j in range (n + 1 )] for i in range (k + 1 )]
m = 0
while dp[m][n] < k:
m + = 1
for x in range ( 1 , n + 1 ):
dp[m][x] = 1 + dp[m - 1 ][x - 1 ] + dp[m - 1 ][x]
return m
if __name__ = = '__main__' :
print (minTrials( 2 , 10 ))
|
Output
4
Time Complexity: O(n*k)
Auxiliary Space: O(n*k)
Optimization to one-dimensional DP
The above solution can be optimized to one-dimensional DP as follows:
C++
#include <bits/stdc++.h>
using namespace std;
int minTrials( int n, int k)
{
int dp[n + 1] = { 0 }, m;
for (m = 0; dp[n] < k; m++) {
for ( int x = n; x > 0; x--) {
dp[x] += 1 + dp[x - 1];
}
}
return m;
}
int main()
{
cout << minTrials(2, 10);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int minTrials( int n, int k)
{
int dp[] = new int [n + 1 ], m;
for (m = 0 ; dp[n] < k; m++)
{
for ( int x = n; x > 0 ; x--)
{
dp[x] += 1 + dp[x - 1 ];
}
}
return m;
}
public static void main(String[] args)
{
System.out.println(minTrials( 2 , 10 ));
}
}
|
Python3
def minTrials(n, k):
dp = [ 0 ] * (n + 1 )
m = 0
while dp[n] < k:
m + = 1
for x in range (n, 0 , - 1 ):
dp[x] + = 1 + dp[x - 1 ]
return m
print (minTrials( 2 , 10 ))
|
C#
using System;
public class GFG {
static int minTrials( int n, int k)
{
int [] dp = new int [n + 1];
int m = 0;
for (; dp[n] < k; m++) {
for ( int x = n; x > 0; x--) {
dp[x] += 1 + dp[x - 1];
}
}
return m;
}
static public void Main()
{
Console.WriteLine(minTrials(2, 10));
}
}
|
Javascript
function minTrials(n, k) {
let dp = new Array(n + 1).fill(0);
let m = 0;
while (dp[n] < k) {
m += 1;
for (let x = n; x > 0; x--) {
dp[x] += 1 + dp[x - 1];
}
}
return m;
}
console.log(minTrials(2, 10));
|
Output
4
Complexity Analysis:
- Time Complexity: O(n * log k)
- Auxiliary Space: O(n)
Please Login to comment...