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