100層樓2個雞蛋,如何得知雞蛋能承受幾層的撞擊

1、題目:
  有一棟樓共100層,一個雞蛋從第N層及以上的樓層落下來會摔破, 在第N層如下的樓層落下不會摔破。給你2個雞蛋,設計方案找出N,而且保證在最壞狀況下, 最小化雞蛋下落的次數。面試

 

解答2:得5分的答案數組

 

若是咱們動一下腦子仔細思考這個問題,咱們會獲得一個相對不錯的答案。參加BAT面試那位朋友就給出了下面的這種方案,並自認爲是一種很完美的答案。但面試官給出的回答是:我仍是不滿意。測試

 

聽說,他這種思路的靈感來自於數學中的求極值問題。優化

 

已知兩個天然數的和爲25,求這兩個數的平方和的最大、最小值。spa

解:設一個天然數爲x 另外一個天然數爲25-x設計

x²+(25-x)²code

=2x²-50x+625數學

=2(x²-25x+312.5)class

=2[(x-12.5)²-156.25+312.5]原理

=2[(x-12.5)²+156.25]

因此可得:

當x取12.5時 有最小值2×156.25=312.5  (當x==y==12.5時取得極小值

當x取25時 有最大值2×(12.5²+156.5)=625

 

所以,很容易獲得啓發(固然,這只是一種直覺,並無什麼理論依據。)。100層樓,平均分紅10分,每份恰好10層。

 

那麼咱們的作法以下:

 

將100層樓分紅10分,每一份就是10層樓。首先,將雞蛋從第10層樓開始扔。那麼結果有兩種可能:

狀況1:若是碎了,說明臨界樓層在1到10之間,但如今只剩下一個雞蛋了,只能從第一層一直到第10層。

狀況2:若是沒有碎,接下來從第20層扔雞蛋。

該方法的思路是,用一個雞蛋來試探,找到臨界樓層的大體範圍[1~10]、[11-20]….[91-100]。而後用另外一個雞蛋在大體範圍內找出精確樓層。該方法的最壞次數是:18次

 

2、思路:
  先假設,最小的次數爲x次。
  首先在x層摔,那麼會出現兩個結果:
  一、碎了,爲了找出那一層碎了,第二個雞蛋必須從1~x-1進行遍歷的摔
  二、沒碎,那麼第二次就在x+(x-1)樓層摔。

爲何是x+x-1樓層呢?
首先咱們已經假設了經過x步咱們就能獲得答案,如今咱們在x層已經用了一次了,那麼就只剩下x-1步了。因此咱們選擇x+(x-1)層,若是碎了,咱們就能經過x-2步,遍歷x+1~x+(x-1)-1的全部樓層。

  三、若是在x+(x-1)樓碎了,那麼同1,遍歷x+1~x+(x-1)-1
  四、沒碎,那麼同2,就在x+(x-1)+(x-2)層摔
  …
  最後咱們將會得出這樣一個樓層公式x+(x-1)+(x-2)+…+1 = x(x+1)/2。
  這個公式有什麼意義呢?
  有, x(x+1)/2 >= 100,這樣才能順利的解除x。
  有人說,x(x+1)/2 = 99就能夠,若是雞蛋在99層都沒碎,那麼一定是100層。 我想說誰告訴你記得必定會碎!
  那麼咱們就順利的解除 x=14。

3、擴展
  此題還有一個擴展,就是爲N個雞蛋從M層摔找出最小值。
  那就不是很好手解了,因此寫了代碼,使用動態規劃原理。動態規劃式子以下:

f[n][m] = 1+max(f[n-1][k-1],f[n][m-k]) k屬於[1,m-1]
解釋下原理:
一、當手裏有n個的時候,雞蛋從k層往下摔,若是破了,那麼手裏只有n-1雞蛋了,那麼就須要測試f[n-1][k-1]樓層。或者更通俗好理解點的,我 們運用2個雞蛋100樓層的題目舉例子。以上式子變爲:f[2][m] = 1+max(f[1][k-1],f[2][m-k])
  那麼當手裏有2個雞蛋的時候,在k層摔,碎了。那麼如今手裏也就只有一個雞蛋了,此時咱們必須遍歷1~k-1找出第一次碎的樓層。因此爲1+f[1][m-k],前面的1表明在k層的操做。
二、沒破,那麼手裏還有n個雞蛋,那麼須要測試k+1~m這些樓層。

此時我想問下,當手裏有2個雞蛋測試1~m-k層和手裏有2個雞蛋測試k+1~m有什麼區別?
有人說有,由於樓層越高越容易碎,那實際上是你我的的想法罷了。其實並無區別,因此第一個公式能夠寫爲f[n][m-k]。

最後附上代碼,爲了理解方便,而沒必要從數組從0開始而困擾,這裏就空間多開了點,因此若是拿去用的話,能夠優化下:

package cglib;

 

 

public class DeleteNode {
    public int countMinSetp(int egg,int num){
        if(egg < 1 || num < 1) return 0;
        int[][] f = new int[egg+1][num+1];//表明egg個雞蛋,從num樓層冷下來所需的最小的次數
        for(int i=1;i<=egg; i++){
            for(int j=1; j<=num; j++)
                f[i][j] = j;//初始化,最壞的步數
        }

        for(int n=2; n<=egg; n++){
            for(int m=1; m<=num; m++){
                for(int k=1; k<m; k++){
                    //這裏的DP的遞推公式爲f[n][m] = 1+max(f[n-1][k-1],f[n][m-k]) k屬於[1,m-1]
                    //從1-m層中隨機抽出來一層k
                    //若是第一個雞蛋在k層碎了,那麼咱們將測試1~k-1層,就能夠找出來,也即1+f[1][k-1],1便是已經扔了一次
                    //若是第一個雞蛋在k層沒有碎,那麼咱們將測試k+1~m也即m-k層,
                    //      這裏也是重點!!!!
                    //      如今咱們手裏有2個雞蛋,要測試m-k層,那麼我想問,此時和你手裏有2個雞蛋要測試1~m-k層有什麼區別?
                    //      沒有區別!是的在已知k層不碎的狀況下,測試k+1~m層的方法和測試1~m-k沒區別,因此能夠寫成 1+f[n][m-k] 其中1表示爲 在k層的那一次測試
                    f[n][m] = Math.min(f[n][m],1+Math.max(f[n-1][k-1],f[n][m-k]));
                }
            }
        }
        return f[egg][num];
    }
    public static void main(String[] args) {
        DeleteNode e = new DeleteNode();
        System.out.println(e.countMinSetp(5,100));
    }
    
    
    }  


輸出:14

 

-------------------------------------------------------------------------------------------------------------------------

有一棟樓共100層,一個雞蛋從第N層及以上的樓層落下來會摔破, 在第N層如下的樓層落下不會摔破。給你2個雞蛋,設計方案找出N,而且保證在最壞狀況下, 最小化雞蛋下落的次數。

咱們先假設最壞狀況下,雞蛋下落次數爲x,即咱們爲了找出N,一共用雞蛋作了x次的實驗。 那麼,咱們第一次應該在哪層樓往下扔雞蛋呢?先讓咱們假設第一次是在第y層樓扔的雞蛋, 若是第一個雞蛋在第一次扔就碎了,咱們就只剩下一個雞蛋,要用它準確地找出N, 只能從第一層向上,一層一層的往上測試,直到它摔壞爲止,答案就出來了。 因爲第一個雞蛋在第y層就摔破了, 因此最壞的狀況是第二個雞蛋要把第1到第y-1層的樓都測試一遍,最後得出結果, 噢,原來雞蛋在第y-1層才能摔破(或是在第y-1層仍沒摔破,答案就是第y層。) 這樣一來測試次數是1+(y-1)=x,即第一次測試要在第x層。OK, 那若是第一次測試雞蛋沒摔破呢,那N確定要比x大,要繼續往上找,須要在哪一層扔呢? 咱們能夠模仿前面的操做,若是第一個雞蛋在第二次測試中摔破了, 那麼第二個雞蛋的測試次數就只剩下x-2次了(第一個雞蛋已經用了2次)。 這樣一來,第二次扔雞蛋的樓層和第一次扔雞蛋的樓層之間就隔着x-2層。 咱們再回過頭來看一看,第一次扔雞蛋的樓層在第x層,第1層到第x層間共x層; 第1次扔雞蛋的樓層到第2次扔雞蛋的樓層間共有x-1層(包含第2次扔雞蛋的那一層), 同理繼續往下,咱們能夠得出,第2次扔雞蛋的樓層到第3次扔雞蛋的樓層間共有x-2層, ……最後把這些互不包含的區間數加起來,應該大於等於總共的樓層數量100,即

x + (x-1) + (x-2) + ... + 1 >= 100
(x+1)*x/2 >= 100

得出答案是14。

即我先用第1個雞蛋在如下序列表示的樓層數不斷地向上測試,直到它摔破。 再用第2個雞蛋從上一個沒摔破的序列數的下一層開始,向上測試, 便可保證在最壞狀況下也只須要測試14次,就能用2個雞蛋找出從哪一層開始, 往下扔雞蛋,雞蛋就會摔破。

14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100

好比,我第1個雞蛋是在第77層摔破的,那麼我第2個雞蛋就從第70層開始,向上測試, 第二個雞蛋最多隻須要測試7次(70,71,72,73,74,75,76),加上第1個雞蛋測試的 7次(14,27,39,50,60,69,77),最壞狀況只須要測試14次便可得出答案。

相關文章
相關標籤/搜索