Coursera Algorithms week1 練習測驗:Egg drop 扔雞蛋問題
轉自 https://www.cnblogs.com/evasean/p/7208986.html
題目原文:
Suppose that you have an n-story building (with floors 1 through n) and plenty of eggs. An egg breaks if it is dropped from floor T or higher and does not break otherwise. Your goal is to devise a strategy to determine the value of T given the following limitations on the number of eggs and tosses:
Version 0: 1 egg, ≤T tosses.
Version 1: ∼1lgn eggs and ∼1lgn tosses.
Version 2: ∼lgT eggs and ∼2lgT tosses.
Version 3: 2 eggs and ∼2
tosses.
Version 4: 2 eggs and ≤c
tosses for some fixed constant c
分析:
version0 : 拿著一個雞蛋從1~n依次扔就可以,到floor T會碎,故複雜度為≤T
version 1: 採用二分查詢,首先從n/2層開始扔:
if(雞蛋碎) 從(n/2)/2層開始扔;
else 從n/2+(n/2)/2層開始扔
二分方法需要lgn個雞蛋嘗試lgn次
version 2: 依次從1, 2, 4, 8, 16, 32,…2k開始扔,如果雞蛋在2k
version 3: 將0~n層樓分成[1, -1], [ , 2 -1], [2 ,3 -1]…[k , (k+1) -1]…個區間,用一個雞蛋分佈從1開始在各個區間的起始樓層扔,如果在k 層碎了,那就從(k-1) +1開始逐層扔。第一步區間選擇用了 的複雜度,第二步區間內部扔雞蛋用了 的複雜度,總共用了2
version 4: 嘗試從1, 4, 9, 16, 25,…(k-1)2, k2…樓層扔雞蛋,加入雞蛋在樓層k2碎了,意味著(k-1)2≤T≤k2,這一步嘗試了 次(k= )。接著從樓層(k-1)2+1開始逐層扔,最多嘗試至k2-1結束,這一步需要嘗試k2-1-(k-1)2-1=2 -1=2 -2次。總共用了3 -2次
程式碼實現
package eggdrop;
public class EggDrop {
//供預測的提前設定的解,也可以直接random一個,為方便測試直接給定。
public static int T = 10;
//嘗試了幾次
static int numsOfTry = 0;
//摔碎了多少個雞蛋
static int numsOfEggBroken = 0;
//扔雞蛋抽象為一個方法,扔的時候更新嘗試次數和雞蛋碎了沒有的次數,同時列印嘗試的過程和結果
public static boolean drop(int i){
numsOfTry++;
if(i < T) {
System.out.println("from " + i + " no");
return false;
}
else{
System.out.println("from " + i + " yes");
numsOfEggBroken++;
return true;
}
}
//以下為version0-4的實現,前面註釋給出的兩個數字分別為
//(摔壞的雞蛋數的期望,嘗試次數的期望)
//1egg;T
public static void go0(int n){
for (int i = 0; i < n; i++) {
boolean tmp = drop(i);
if(tmp == true) {
System.out.println("T is " + i);
break;
}
}
}
//lg(n)egg;lg(n)
//為方便go2呼叫,把其改為了帶上下界的二分的方法。
public static void go1(int n,int start,int end){
boolean tmp = drop((start + end) / 2);;
while(start < end) {
if (tmp == false) {
start = (start + end) / 2 + 1;
tmp = drop((start + end) / 2);
}
else{
end = (start + end) / 2 - 1;
tmp = drop((start + end) / 2);
}
}
if(tmp == false){
System.out.println("T is " + ((start + end) / 2 + 1));
}else{
System.out.println("T is " + (start + end) / 2);
}
}
//lg(T)egg;2lg(T)
public static void go2(int n){
int k = -1;
int start = 0;
int end = n - 1;
for (int i = 0; i < Math.sqrt(n) - 1; i++) {
int t = (int)Math.pow(2,(double)i);
boolean tmp = drop(t);
if(tmp == true){
k = (int)Math.pow(2,(double)i);
start = (int)Math.pow(2,(double)i - 1);
end =(int)Math.pow(2,(double)i);
break;
}
}
go1(n, 0 ,n - 1);
}
//2egg;2根號n
public static void go3(int n){
int l = (int) Math.sqrt(n);
int k = -1;
for (int i = 0; i * l < n; i++) {
boolean tmp = drop(i * l);
if(tmp == true){
k = i;
break;
}
}
for (int i = (k-1) * l + 1; i < k * l; i++) {
boolean tmp = drop(i);
if(tmp == true){
System.out.println("\nT is " + i);
break;
}
}
}
//2egg ;3根號T
public static void go4(int n){
int k = -1;
for (int i = 0; Math.pow(i, 2) < n; i++) {
boolean tmp = drop((int)Math.pow(i, 2));
if(tmp == true){
k = i;
break;
}
}
for (int i = (int)Math.pow(k-1, 2) + 1; i < Math.pow(k, 2); i++) {
boolean tmp = drop(i);
if(tmp == true){
System.out.println("\nT is " + i);
break;
}
}
}
public static void main(String[] args) {
int n = 40;
//方便go2呼叫
//go1(n,0, n-1);
go4(n);
System.out.println("Number of the Broken Eggs is " + numsOfEggBroken);
System.out.println("Number of trying is " + numsOfTry);
}
}