智力題(程式設計師面試經典)
阿新 • • 發佈:2019-01-05
解法
我們發現,無論怎麼扔雞蛋1(Egg 1),雞蛋2(Egg 2)都必須在“破掉那一層”和下一個不會破掉的最高樓層之間,逐層扔下樓(從最低的到最高的)。例如,若雞蛋1從5層和10層樓扔下沒破掉,但從15層扔下時破掉了,那麼,在最差情況下,雞蛋2必須嘗試從11、12、13和14層扔下樓。
具體做法
首先,讓我們試著從10層開始扔雞蛋,然後是20層,等等。
如果雞蛋1第一次扔下樓(10層)就破掉了,那麼,最多需要扔10次。
如果雞蛋1最後一次扔下樓(100層)才破掉,那麼,最多要扔19次(10、20、…、90、100層,然後是91到99層)。
這麼做也挺不錯,但我們只考慮了絕對最差情況。我們應該進行“負載均衡”,讓這兩種情況下扔雞蛋的次數更均勻。
我們的目標是設計一種扔雞蛋的方法,使得扔雞蛋1時,不論是在第一次還是最後一次扔下樓才破掉,次數越穩定越好。
(1) 完美負載均衡的方法應該是,扔雞蛋1的次數加上扔雞蛋2的次數,不論什麼時候都一樣,不管雞蛋1是從哪層樓扔下時破掉的。
(2) 若有這種扔法,每次雞蛋1多扔一次,雞蛋2就可以少扔一次。
(3) 因此,每丟一次雞蛋1,就應該減少雞蛋2可能需要扔下樓的次數。例如,如果雞蛋1先從20層往下扔(不破),然後從30層扔下樓(破),此時雞蛋2可能就要扔9次(從21到29 一次次試)。若雞蛋1再扔一次,我們必須讓雞蛋2扔下樓的次數降為8次。也就是說,我們必須讓雞蛋1從39層扔下樓。
(4) 由此可知,雞蛋1必須從X層開始往下扔,然後再往上增加X-1層……直至到達100層。
(5) 求解方程式X + (X-1) + (X-2) + … + 1 = 100,得到X (X + 1) / 2 = 100 → X = 14。 (直接設要X次,假如X 和X-1這兩次了 則再加X-2 總共還是X次, 次數總為X)
我們先從14層開始,然後是27層,接著是39層,依此類推,最差情況下雞蛋要扔14次。
正如解決其他許多最大化/最小化的問題一樣,這類問題的關鍵在於“平衡最差情況”。
NO.6
走廊上有100個關上的儲物櫃。有個人先是將100個櫃子全都開啟。接著,每數兩個櫃子關上一個。然後,在第三輪時,再每隔兩個就切換第三個櫃子的開關狀態(也就是將關上的櫃子開啟,將開啟的關上)。照此規律反覆操作100次,在第i輪,這個人會每數i個就切換第i個櫃子的狀態。當第100輪經過走廊時,只切換第100個櫃子的開關狀態,此時有幾個櫃子是開著的?
解法
要解決這個問題,我們必須弄清楚所謂切換儲物櫃開關狀態是什麼意思。這有助於我們推斷最終哪些櫃子是開著的。
1. 問題:櫃子會在哪幾輪切換狀態(開或關)?
櫃子n會在n的每個因子(包括1和n本身)對應的那一輪切換狀態。也就是說,櫃子15會在第1、3、5和15輪開或關一次。(i=1開,3關,5開,15關。因子個數:偶數關,奇數開)
2. 問題:櫃子什麼時候還是開著的?
如果因子個數(記作x)為奇數,則這個櫃子是開著的。你可以把一對因子比作開和關,若還剩一個因子,則櫃子就是開著的。
3. 問題:x什麼時候為奇數?
若n為完全平方數,則x的值為奇數。理由如下:將n的兩個互補因子配對。例如,如n為36,則因子配對情況為:(1, 36)、(2, 18)、(3, 12)、(4, 9)、(6, 6)。注意,(6, 6)其實只有一個因子,因此n的因子個數為奇數。
4. 問題:有多少個完全平方數?
一共有10個完全平方數,你可以數一數(1、4、9、16、25、36、49、64、81、100),或者,直接列出1到10的平方:
1*1, 2*2, 3*3, ..., 10*10
因此,最後共有10個櫃子是開著的。
以上內容選自《Cracking the Coding Interview: 150 Programming Questions and Solutions, 5th Edition》中文版《程式設計師面試金典(第5版)》瞭解更多面試題,請關注這本書。