最近在 leetcode 上看到了一道題 Super Egg Drop, 剛好之前看到過一到很類似的題,就是 google 的一道經典的面試題。這裡記錄一下自己整個的解題思路。
google 原題
給你兩個雞蛋,它們有可能都在某一層樓往下摔就會摔碎,也可能從一百層樓摔下來沒事。有座100層的建築,要你用這兩個雞蛋通過最少的次數確定哪一層是雞蛋摔碎的臨界點。每次實驗即使沒摔碎也不會對雞蛋有損耗。
思路
這是一道很經典的需要用到動態規劃的題目,我們每一次扔雞蛋的結果都會影響我們後續扔的次數,比方說我們上來就從 90 層扔,如果碎了,我們就得從1樓一層一層往上扔到90層才能試出結果,如果沒碎,我們只需要在 90 ~ 100 這 10 層做實驗即可。
要用動態規劃的來解這道題,我們首先要列出問題中的狀態
每次我們扔雞蛋的時候,可能會出現兩種狀態
- 摔碎,這時下一個雞蛋就要從最底層一個一個往上試才能試出結果
- 沒碎,則我們需要根據剩餘的樓層數來決策出我們下一次丟雞蛋的樓層數
我們假設第一次我們從 x 層樓往下扔,如果雞蛋沒碎,下一次我們往上走 k 層樓再扔,根據我們的假設我們可以繪製出一個這樣的決策樹。
為了讓最壞的情況不太壞,我們必須要保證每一次的決策最後所需要的次數都儘可能的相等。也就是
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 >=
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] =
當 k > 2時
假設我們還剩 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)
這題後面還需要優化,由於複雜度較高,需要一定的基礎,暫時沒有繼續優化下去
推薦一個人的部落格,把這題分析的非常透徹,有興趣的可以看看
部落格地址