一摞烙餅的排序(0621)

2021-05-22 21:16:00 字數 1466 閱讀 9309

每乙個演算法都值得好好地分析

問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?

這個排序問題非常有意思,首先我們要弄清楚解決問題的關鍵操作——「單手每次抓幾塊餅,全部顛倒」。

每次我們只能選擇最上方的一堆餅,一起翻轉。而不能一張張地直接抽出來,然後進行插入,也不能交換任意兩塊餅子。這說明基本的排序辦法都不太好用。那麼怎麼把這n個烙餅排好序呢?

由於每次操作都是針對最上面的餅,如果最底層的餅已經排序,那我們只用處理上面的n-1個烙餅。這樣,我們可以再簡化為n-2、n-3,直到最上面的兩個餅排好序。

【解法一】

我們用圖1-7演示一下,為了把最大的烙餅擺在最下面,我們先把最上面的烙餅和最大的烙餅之間的烙餅翻轉(1~4之間),這樣,最大的烙餅就在最上面了。接著,我們把所有烙餅翻轉(4~5之間),最大的烙餅就擺在最下面了。

兩次翻轉烙餅,調整最大的烙餅到最底端

之後,我們對上面n-1、n-2個餅重複這個過程就可以了。

那麼,我們一共需要多少次翻轉才能把這些烙餅給翻轉過來呢?

首先,經過兩次翻轉可以把最大的烙餅翻轉到最下面。因此,最多需要把上面的n-1個烙餅依次翻轉兩次。那麼,我們至多需要2(n-1)次翻轉就可以把所有烙餅排好序(因為第二小的烙餅排好的時候,最小的烙餅已經在最上面了)。

這樣看來,單手翻轉的想法是肯定可以實現的。我們進一步想想怎麼減少翻轉烙餅的次數吧。

怎樣才能通過程式來搜尋到乙個最優的方案呢?

首先,通過每次找出最大的烙餅進行翻轉是乙個可行的解決方案。那麼,這個方案是最好的乙個嗎?考慮這樣一種情況,假如這堆烙餅中有好幾個不同的部分相對有序,憑直覺來猜想,我們可以先把小一些的烙餅進行翻轉,讓其有序。這樣會比每次翻轉最大的烙餅要更快。

既然如此,有類似的方案可以達到目的嗎?比如說,考慮每次翻轉的時候,把兩個本來應該相鄰在烙餅盡可能地換到一起。這樣,當所有的烙餅都換到一起之後,實際上就是完成排序了。(從這個意義上來說,每次翻最大烙餅的方案實質上就是每次把最大的和次大的交換到一起。)

在這樣的基礎之上,本能的乙個想法就是窮舉。只要窮舉出所有可能的交換方案,那麼,我們一定能夠找到乙個最優的方案。

沿著這個思路去考慮,我們自然就會使用動態規劃或者遞迴的方法來進行實現了。可以從不同的翻轉策略開始,比如說第一次先翻最小的,然後遞迴把所有的可能全部翻轉一遍。這樣,最終肯定是可以找到乙個解的。

但是,既然是遞迴就一定有退出的條件。在這個過程中,第乙個退出的條件肯定是所有的烙餅已經排好序。那麼,有其他的嗎?如果大家仔細想想就會發現到,既然2(n-1)是乙個最多的翻轉次數。如果在演算法中,需要翻轉的次數多於2(n-1),那麼,我們就應該放棄這個翻轉演算法,直接退出。這樣,就能夠減少翻轉的次數。

從另外乙個層面上來說,既然這是乙個排序問題。我們也應該利用到排序的資訊來進行處理。同樣,在翻轉的過程中,我們可以看看當前的烙餅陣列的排序情況如何,然後利用這些資訊來幫助減少翻轉次數的判斷過程。

下面是在前面討論的基礎之上形成的乙個粗略的搜尋最優方案的程式:

使用這個類的時候直接呼叫就可以了

1 3 一摞烙餅的排序

一摞亂序擺放的烙餅,每次只能抓取最上面幾塊烙餅並翻轉,多次翻轉後能夠實現烙餅的從小到大 從上往下 的有序擺放。問題分析 這裡我們使用回溯法解決這個問題。直接用回溯法效率是低下的,因此要進行剪枝。這裡的剪枝條件是利用翻轉次數的上界和下界完成的。上界 4,2,1,5,3 5,1,2,4,3 3,4,2,...

1 3 一摞烙餅的排序

假設有n塊大小不一樣的烙餅,那麼最少要翻動幾次,才能達到最終有序的結果。思路 每次找到最大的然後從將最大的以及最大的上面的反轉,這時候最大的在最上面,然後將整個反轉,最大的就在最下面了。然後再對除了最下面的n 1個烙餅進行上述的操作,知道全部的烙餅有序。例如 13524 53124 42135 cl...

一摞烙餅的排序 搜尋樹

前兩個星期就看程式設計之美的一摞烙餅排序問題,剛開始看其 沒看懂什麼意思,後來看了人家的部落格才知道是怎麼回事了,自己寫了一遍其 做各種各樣的測試,嚇我一跳,乙個剪枝操作竟然省了那麼多的時間,想起上一道題的將帥問題,頓時讓我領悟到這程式設計之美的書籍,題目不但有意思,其 真的優雅和美,好了接下來看這...