【轉】漫畫:經典谷歌面試題“扔雞蛋”,看看你會做嗎?

640?wx_fmt=gif

640?wx_fmt=jpeg640?wx_fmt=jpeg

640?wx_fmt=png

 第二天


640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=png

題目:扔雞蛋問題


有2個雞蛋,從100層樓上往下扔,以此來測試雞蛋的硬度。比如雞蛋在第9層沒有摔碎,在第10層摔碎了,那麼雞蛋不會摔碎的臨界點就是9層。

問:如何用最少的嘗試次數,測試出雞蛋不會摔碎的臨界點?

640?wx_fmt=png


舉個栗子,最笨的測試方法,是什麼樣的呢?把其中一個雞蛋,從第1層開始往下扔。如果在第1層沒碎,換到第2層扔;如果在第2層沒碎,換到第3層扔.......如果第59層沒碎,換到第60層扔;如果第60層碎了,說明不會摔碎的臨界點是第59層。

在最壞情況下,這個方法需要扔100次。

640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=png

方法一:二分法


採用類似於二分查找的方法,把雞蛋從一半樓層(50層)往下扔。

如果第一枚雞蛋,在50層碎了,第二枚雞蛋,就從第1層開始扔,一層一層增長,一直扔到第49層。

如果第一枚雞蛋在50層沒碎了,則繼續使用二分法,在剩餘樓層的一半(75層)往下扔......

這個方法在最壞情況下,需要嘗試50次。

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=png

方法二:平方根法


如何讓第一枚雞蛋和第二枚雞蛋的嘗試次數,儘可能均衡呢?

很簡單,做一個平方根運算,100的平方根是10。

因此,我們嘗試每10層扔一次,第一次從10層扔,第二次從20層扔,第三次從30層......一直扔到100層。

這樣的最好情況是在第10層碎掉,嘗試次數爲 1 + 9 = 10次。

最壞的情況是在第100層碎掉,嘗試次數爲 10 + 9 = 19次。

640?wx_fmt=png

不過,這裏有一個小小的優化點,我們可以從15層開始扔,接下來從25層、35層扔......一直到95層。

這樣最壞情況是在第95層碎掉,嘗試次數爲 9 + 9 = 18次。

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=png


640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=png640?wx_fmt=jpeg640?wx_fmt=jpeg

640?wx_fmt=jpeg640?wx_fmt=jpeg

640?wx_fmt=png

假設最優的嘗試次數的x次,爲什麼第一次扔就要選擇第x層呢?

這裏的解釋會有些燒腦,請小夥伴們坐穩扶好:

假設第一次扔在第x+1層:

如果第一個雞蛋碎了,那麼第二個雞蛋只能從第1層開始一層一層扔,一直扔到第x層。

這樣一來,我們總共嘗試了x+1次,和假設嘗試x次相悖。由此可見,第一次扔的樓層必須小於x+1層。

假設第一次扔在第x-1層:

如果第一個雞蛋碎了,那麼第二個雞蛋只能從第1層開始一層一層扔,一直扔到第x-2層。

這樣一來,我們總共嘗試了x-2+1 = x-1次,雖然沒有超出假設次數,但似乎有些過於保守。

假設第一次扔在第x層:

如果第一個雞蛋碎了,那麼第二個雞蛋只能從第1層開始一層一層扔,一直扔到第x-1層。

這樣一來,我們總共嘗試了x-1+1 = x次,剛剛好沒有超出假設次數。

因此,要想盡量樓層跨度大一些,又要保證不超過假設的嘗試次數x,那麼第一次扔雞蛋的最優選擇就是第x層。

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg640?wx_fmt=jpeg

640?wx_fmt=png

640?wx_fmt=jpeg


640?wx_fmt=png

方法三:解方程法


x + (x-1) + (x-2) + ... + 1 = 100

這個方程式不難理解:

左邊的多項式是各次扔雞蛋的樓層跨度之和。由於假設嘗試x次,所以這個多項式共有x項。

右邊是總的樓層數100。

下面我們來解這個方程:

x + (x-1) + (x-2) + ... + 1 = 100  轉化爲

(x+1)*x/2 = 100

最終x向上取整,得到 x = 14

因此,最優解在最壞情況的嘗試次數是14次,第一次扔雞蛋的樓層也是14層。

最後,讓我們把第一個雞蛋沒碎的情況下,所嘗試的樓層數完整列舉出來:

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

舉個栗子驗證下:

假如雞蛋不會碎的臨界點是65層,那麼第一個雞蛋扔出的樓層是14,27,50,60,69。這時候啪的一聲碎了。

第二個雞蛋繼續,從61層開始,61,62,63,64,65,66,啪的一聲碎了。

因此得到不會碎的臨界點65層,總嘗試次數是 6 + 6 = 12 < 14 。

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg



首先,題目提到只有“兩個雞蛋” “兩個雞蛋” “兩個雞蛋”,要知道第一個雞蛋用來試錯的, 只要它從 k 層樓扔下去沒碎, 則目標就在[k+1, 100]之間了.
但一旦運氣不好碎了, 對於已知的區間, 我們只能用剩下一個雞蛋從小到大一層層試,
因爲我們要保證策略必須成功, 不能冒險了.

"最壞情況下代價最小"這句話十分重要, 它反映了題目的重要數學結構:
我們可以把任何一種策略都看成一個決策樹,
每一次扔雞蛋都會有兩個子節點, 對應碎與不碎的情況下下一步應該扔的樓層.
那麼, 策略的一次執行, 是樹中的一條從根往下走的路,
當且僅當這條路上出現過形如 k 沒碎 與 k+1 碎了的一對節點時, 路停止, 當前節點不再擴展.
那麼要找的是這麼一棵樹, 使得所有路里最長者儘量短, 也即, 要找一個最矮的決策樹.

基於數學方程的方法(通俗版)

假設最少嘗試次數爲x,那麼,第一個雞蛋必須要從第x層扔下,因爲:如果碎了,前面還有x - 1層樓可以嘗試,如果沒碎,後面還有x-1次機會。

如果沒碎,第一個雞蛋,第二次就可以從x +x - 1)層進行嘗試,爲什麼是加上x - 1,因爲,當此時,第一個雞蛋碎了,第二個雞蛋還有可以從x+1 到 x + (x - 1) - 1層進行嘗試,有(x+1)+(x + (x - 1) - 1)+1=x - 2次。如果還沒碎,那第一個雞蛋,第三次從 x + (x - 1) + (x - 2)層嘗試。碎或者沒碎,都有x - 3次嘗試機會,依次類推。那麼,x次的最少嘗試,可以確定的最高的樓層是多少呢? x + (x - 1) + (x - 2) + … + 1 = x(x+1) / 2 那反過來問,當最高樓層是100層,最少需要多少次呢?x(x+1)/2 >= 100, 得到x>=14,最少要嘗試14次。

640?wx_fmt=gif

640?wx_fmt=gif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章