一摞饼的排序
? ? ? ?這是《編程之美》中的一道題,以下是我的學(xué)習(xí)心得。
一,問題:????????????
????????星期五的晚上,一幫同事在希格瑪大廈附近的“硬盤酒吧”多喝了幾杯。程序員多喝了幾杯之后談什么呢?自然是算法問題。有個同事說:“我以前在餐館打工,顧客經(jīng)常點非常多的烙餅。店里的餅大小不一,我習(xí)慣在到達(dá)顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由于我一只手托著盤子,只好用另一只手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反復(fù)幾次之后,這摞烙餅就排好序了。我后來想,這實際上是個有趣的排序問題:假設(shè)有n塊大小不一的烙餅,那最少要翻幾次,才能達(dá)到最后大小有序的結(jié)果呢?”
????????你能否寫出一個程序,對于n塊大小不一的烙餅,輸出最優(yōu)化的翻餅過程呢?(參考http://blog.sina.com.cn/s/blog_a2aa00d70101ewuf.html)
問題的關(guān)鍵是,單手每次抓幾塊餅,全部顛倒。具體參考如圖1-1所示
? ?
變?yōu)?/strong>
? ? ? ? ? ? ? ? ? ? ? ? 圖1-1
每次只能選擇最上方的一堆餅,一起翻轉(zhuǎn),而不能一張張的直接抽出來,然后進(jìn)行插入,也不能交換任意兩塊餅。
? 圖1-2演示一下,為了把最大的烙餅擺在最下面,先把最上面的和最大的烙餅之間翻轉(zhuǎn),這樣,最大的烙餅就在最上面了。接著,把所有烙餅翻轉(zhuǎn),最大的烙餅在最下面了。
變?yōu)?/strong>
變?yōu)?/strong>
? ? ? ? ? ? ? ? ? ? ? ? ?圖1-2
這是一特殊的例子,經(jīng)過兩次翻轉(zhuǎn)即實現(xiàn)了。兩次翻轉(zhuǎn)就可以把最大的烙餅翻轉(zhuǎn)到最下面。因此,最多需要把上面的n-1個烙餅依次翻轉(zhuǎn)兩次。那么我們至多需要2(n-1)次翻轉(zhuǎn)就可以把所有烙餅排好序。
? ?單手翻轉(zhuǎn)可以實現(xiàn),進(jìn)一步想,怎樣減少翻轉(zhuǎn)烙餅的次數(shù)呢。
? ?考慮這樣一種情況,假如這堆烙餅中有好幾個不同的部分相對有序,憑直覺來猜,可以先把小的烙餅進(jìn)行翻轉(zhuǎn),讓其有序,這樣會比每次翻轉(zhuǎn)最大的烙餅要更快。
? ?把兩個本來應(yīng)該相鄰的烙餅盡可能地?fù)Q到一起。這樣,等所有烙餅都換到一起之后,實際上就是完成排序了。(從這個醫(yī)院上講,每次翻轉(zhuǎn)最大烙餅的方案實質(zhì)上就是每次把最大的和次大的交換到一起)
? ?在這個基礎(chǔ)上,本能的想法是窮舉。只要窮舉出所有可能的交換方案,那么,我們一定能找到最優(yōu)的一個。
? ?沿著這個思路,我們自然用動態(tài)規(guī)劃或遞歸的方法實現(xiàn),可以從不同的翻轉(zhuǎn)策略開始,比如第一次翻轉(zhuǎn)最小的,然后遞歸把所有的可能全部翻轉(zhuǎn)一遍,這樣,最終肯定是可以找到一個解的。
? 遞歸的退出條件是什么呢?第一個退出條件是所有烙餅已經(jīng)排好序。既然2(n-1)是一個最多的翻轉(zhuǎn)次數(shù),那么在算法中,需要翻轉(zhuǎn)次數(shù)多于2(n-1),我們就應(yīng)該放棄這個方案。
??
? ?
總結(jié)
- 上一篇: 独享版虚拟主机、共享版虚拟主机和云服务器
- 下一篇: 阿里云独享虚拟主机和共享虚拟主机区别对比