Eggs dropping puzzle (Binomial Coefficient and Binary Search Solution)
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++
// C++ program to find minimum // number of trials in worst case. #include <bits/stdc++.h> using namespace std; // Find sum of binomial coefficients xCi // (where i varies from 1 to n). 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; } // Do binary search to find minimum // number of trials in worst case. int minTrials( int n, int k) { // Initialize low and high as 1st // and last floors int low = 1, high = k; // Do binary search, for every mid, // find sum of binomial coefficients and // check if the sum is greater than k or not. while (low <= high) { int mid = (low + high) / 2; if (binomialCoeff(mid, n, k) < k) low = mid + 1; else high = mid; } return low; } /* Driver code*/ int main() { cout << minTrials(2, 10); return 0; } |
Java
// Java program to find minimum // number of trials in worst case. class Geeks { // Find sum of binomial coefficients xCi // (where i varies from 1 to n). If the sum // becomes more than K 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; } // Do binary search to find minimum // number of trials in worst case. static int minTrials( int n, int k) { // Initialize low and high as 1st // and last floors int low = 1 , high = k; // Do binary search, for every mid, // find sum of binomial coefficients and // check if the sum is greater than k or not. while (low <= high) { int mid = (low + high) / 2 ; if (binomialCoeff(mid, n, k) < k) low = mid + 1 ; else high = mid; } return low; } /* Driver code*/ public static void main(String args[]) { System.out.println(minTrials( 2 , 10 )); } } // This code is contributed by ankita_saini |
Python3
# Python3 program to find minimum # number of trials in worst case. # Find sum of binomial coefficients # xCi (where i varies from 1 to n). # If the sum becomes more than K 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 # Do binary search to find minimum # number of trials in worst case. def minTrials(n, k): # Initialize low and high as # 1st and last floors low = 1 high = k # Do binary search, for every # mid, find sum of binomial # coefficients and check if # the sum is greater than k or not. while (low < = high): mid = (low + high) / / 2 if (binomialCoeff(mid, n, k) < k): low = mid + 1 else : high = mid return low # Driver Code print (minTrials( 2 , 10 )) # This code is contributed # by mits |
Javascript
// C# program to find minimum // number of trials in worst case. using System; class GFG { // Find sum of binomial coefficients // xCi (where i varies from 1 to n). // If the sum becomes more than K 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; } // Do binary search to find minimum // number of trials in worst case. static int minTrials(int n, int k) { // Initialize low and high // as 1st and last floors int low = 1, high = k; // Do binary search, for every // mid, find sum of binomial // coefficients and check if the // sum is greater than k or not. while (low <= high) { int mid = (low + high) / 2; if (binomialCoeff(mid, n, k) < k) low = mid + 1; else high = mid; } return low; } // Driver Code public static void Main() { Console.WriteLine(minTrials(2, 10)); } } // This code is contributed // by Akanksha Rai(Abby_akku) |
PHP
<?php // PHP program to find minimum // number of trials in worst case. // Find sum of binomial coefficients // xCi (where i varies from 1 to n). // If the sum becomes more than K function binomialCoeff( $x , $n , $k ) { $sum = 0; $term = 1; for ( $i = 1; $i <= $n && $sum < $k ; ++ $i ) { $term *= $x - $i + 1; $term /= $i ; $sum += $term ; } return $sum ; } // Do binary search to find minimum // number of trials in worst case. function minTrials( $n , $k ) { // Initialize low and high as // 1st and last floors $low = 1; $high = $k ; // Do binary search, for every // mid, find sum of binomial // coefficients and check if // the sum is greater than k or not. while ( $low < $high ) { $mid = ( $low + $high ) / 2; if (binomialCoeff( $mid , $n , $k ) < $k ) $low = $mid + 1; else $high = $mid ; } return (int) $low ; } // Driver Code echo minTrials(2, 10); // This code is contributed // by Akanksha Rai(Abby_akku) ?> |
Javascript
<script> // Javascript program to find minimum // number of trials in worst case. // Find sum of binomial coefficients xCi // (where i varies from 1 to n). If the sum // becomes more than K 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; } // Do binary search to find minimum // number of trials in worst case. function minTrials(n, k) { // Initialize low and high as 1st //and last floors var low = 1, high = k; // Do binary search, for every mid, // find sum of binomial coefficients and // check if the sum is greater than k or not. while (low < high) { var mid = parseInt((low + high) / 2); if (binomialCoeff(mid, n, k) < k) low = mid + 1; else high = mid; } return low; } // Driver code document.write(minTrials(2, 10)); // This code is contributed by shivanisinghss2110 </script> |
4
Time Complexity : O(n Log k)
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++
// C++ program to find minimum number of trials in worst // case. #include <bits/stdc++.h> using namespace std; int minTrials( int n, int k) { // Initialize 2D of size (k+1) * (n+1). vector<vector< int > > dp(k + 1, vector< int >(n + 1, 0)); int m = 0; // Number of moves 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; } /* Driver code*/ int main() { cout << minTrials(2, 10); return 0; } // This code is contributed by Arihant Jain (arihantjain01) |
Java
// Java program to find minimum number of trials in worst // case. import java.util.*; class GFG { // Returns minimum number of trials in worst case // with n eggs and k floors static int minTrials( int n, int k) { // Initialize 2D of size (k+1) * (n+1). int dp[][] = new int [k + 1 ][n + 1 ]; int m = 0 ; // Number of moves 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; } // Driver code public static void main(String[] args) { System.out.println(minTrials( 2 , 10 )); } } //This code contributed by SRJ |
C#
// C# program to find minimum number of trials in worst // case. using System; class GFG { static int minTrials( int n, int k) { // Initialize 2D of size (k+1) * (n+1). int [, ] dp = new int [k + 1, n + 1]; int m = 0; // Number of moves 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)); } } // This code is contributed by garg28harsh. |
Javascript
// Javascript program to find minimum number of trials in worst // case. function minTrials( n, k) { // Initialize 2D of size (k+1) * (n+1). 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; // Number of moves 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)); // This code is contributed by garg28harsh. |
Output
4
Optimization to one-dimensional DP
The above solution can be optimized to one-dimensional DP as follows:
C++
// C++ program to find minimum number of trials in worst // case. #include <bits/stdc++.h> using namespace std; int minTrials( int n, int k) { // Initialize array of size (n+1) and m as moves. 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; } /* Driver code*/ int main() { cout << minTrials(2, 10); return 0; } // This code is contributed by Arihant Jain (arihantjain01) |
Output
4
Complexity Analysis:
- Time Complexity: O(n * log k)
- Auxiliary Space: O(n)
Please Login to comment...