google經典演算法面試題-雞蛋問題

SHISME發表於2019-02-03

最近在 leetcode 上看到了一道題 Super Egg Drop, 剛好之前看到過一到很類似的題,就是 google 的一道經典的面試題。這裡記錄一下自己整個的解題思路。

google 原題

給你兩個雞蛋,它們有可能都在某一層樓往下摔就會摔碎,也可能從一百層樓摔下來沒事。有座100層的建築,要你用這兩個雞蛋通過最少的次數確定哪一層是雞蛋摔碎的臨界點。每次實驗即使沒摔碎也不會對雞蛋有損耗。

思路

這是一道很經典的需要用到動態規劃的題目,我們每一次扔雞蛋的結果都會影響我們後續扔的次數,比方說我們上來就從 90 層扔,如果碎了,我們就得從1樓一層一層往上扔到90層才能試出結果,如果沒碎,我們只需要在 90 ~ 100 這 10 層做實驗即可。

要用動態規劃的來解這道題,我們首先要列出問題中的狀態 每次我們扔雞蛋的時候,可能會出現兩種狀態

  • 摔碎,這時下一個雞蛋就要從最底層一個一個往上試才能試出結果
  • 沒碎,則我們需要根據剩餘的樓層數來決策出我們下一次丟雞蛋的樓層數

我們假設第一次我們從 x 層樓往下扔,如果雞蛋沒碎,下一次我們往上走 k 層樓再扔,根據我們的假設我們可以繪製出一個這樣的決策樹。

01.png
為了讓最壞的情況不太壞,我們必須要保證每一次的決策最後所需要的次數都儘可能的相等。也就是 1 + k = x。所以每次雞蛋沒碎,我們都要再上一次上升樓層數的基礎減少1。

如何確認第一次扔的高度

我們假設我們每次扔雞蛋都沒有碎,第一次從x層開始扔,我們最後一次就必須在100層樓扔了。可以得到式子 x + x - 1 + x - 2 ... + 1 >= 100,根據等差數列求和,我們可以得到 x * (x + 1)/2 >= 100, 得到 x >= 13.45,因為 x 只能取整數,所以第一次我們從14層樓開始扔,得到最壞情況下,我最多需要扔14次可以確認臨界點。

放寬到一般情況,n 層樓 2 個雞蛋,我們可以得到 x + x - 1 + x - 2 ... + 1 >= n 最後算出 x >=

02.png

Super Egg Drop

Super Egg Drop 這道題是 google 這道題的升級版。這裡的是給定 K 個雞蛋,N層樓讓你求出最小的次數是多少。

我們還是按照動態規劃的思路來列出問題中的狀態:

  • K = 0的時候,我們是試不出來的
  • K = 1時,我們只能從1樓一層一層往上試,次數為樓層高度 n
  • K = 2時,情況和上面一樣
  • k > 2時,需要我們單獨分析了

我們設 dp[k][n] 為 k 個雞蛋,n 層樓時的最優次數。

  • k = 0 , dp[k][n] = 0
  • k = 1, dp[k][n] = n
  • k = 2, dp[k][n] =
    01

當 k > 2時

02

假設我們還剩 m 個雞蛋,還需要實驗 n 層樓,此時 1 <= n <= h, 假設我們已經知道了 1 ~ n 層最優解,假設這時候第一次丟的高度為 y ,丟的時候會出現兩種情況, 然後可以列出動態方程

碎了

則此時的最優解為 dp(m - 1, y - 1) + 1

沒碎

則此時的最優解為 dp(m, n - y) + 1

由此我們可以得到 dp(m, n) = min(max(dp(m - 1, y - 1), dp(m, n - y)) + 1), 1<=y< n,由此我們可以遞推的得到 dp(K,N)

JS 實現原始碼

這題後面還需要優化,由於複雜度較高,需要一定的基礎,暫時沒有繼續優化下去

推薦一個人的部落格,把這題分析的非常透徹,有興趣的可以看看 部落格地址

相關文章