1. 程式人生 > >【經典演算法】:烙餅排序

【經典演算法】:烙餅排序

原理非常簡單,看視訊即可

給一個為排序的陣列,你只能再改對該陣列做如下操作:flip(arr, i): 將陣列arr[0...i]進行逆置。如何對該陣列進行排序?

這個問題在程式設計之美一書也有提及:

星期五的晚上,一幫同事在希格瑪大廈附近的“硬碟酒吧”多喝了幾杯。程式設計師多喝了幾杯之後談什麼呢?自然是演算法問題。有個同事說:“我以前在餐館打工,顧客經常點非常多的烙餅。店裡的餅大小不一,我習慣在到達顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由於我一隻手託著盤子,只好用另一隻手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反覆幾次之後,這摞烙餅就排好序了。我後來想,這實際上是個有趣的排序問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?”

你能否寫出一個程式,對於n塊大小不一的烙餅,輸出最優化的翻餅過程呢?

關於這個問題的最優化解法是比較困難的,大家可以參考書上的解法。

這裡只給出直接的解法。演算法思想類似選擇排序,每次找到一個最大的元素,對其進行兩次 flip操作,可將最大的放在最後面,讓後縮小陣列的範圍。因此最大需要 2*(n-1)次flip操作。

可以通過下面的視訊理解這個操作過程:

C++程式碼實現如下:

01 #include <stdlib.h>
02 #include <stdio.h>
03
04 /* 逆置陣列 arr[0..i] */
05 void flip(int arr[],
int i)
06 {
07 int temp, start = 0;
08 while (start < i)
09 {
10 temp = arr[start];
11 arr[start] = arr[i];
12 arr[i] = temp;
13 start++;
14 i--;
15 }
16 }
17
18 /* 找出 arr[0..n-1] 內最大的元素的下標 */
19 int findMax(int arr[], int n)
20 {
21 int mi, i;
22 for (mi = 0, i = 0; i < n; ++i)
23 if (arr[i] > arr[mi])
24 mi = i;
25 return mi;
26 }
27
28 int pancakeSort(int *arr, int n)
29 {
30 // 每次翻轉可以定位一個做大的元素
31 for (int curr_size = n; curr_size > 1; --curr_size)
32 {
33 // 在 arr[0..curr_size-1] 找到最大的元素
34 int mi = findMax(arr, curr_size);
35
36 //記性兩次flip操作,將最大的元素翻轉到最後
37 if (mi != curr_size-1)
38 {
39 flip(arr, mi);
40 flip(arr, curr_size-1);
41 }
42 }
43 }
44
45 /* 列印陣列 */
46 void printArray(int arr[], int n)
47 {
48 for (int i = 0; i < n; ++i)
49 printf("%d ", arr[i]);
50 }
51
52 int main()
53 {
54 int arr[] = {23, 10, 20, 11, 12, 6, 7};
55 int n = sizeof(arr)/sizeof(arr[0]);
56
57 pancakeSort(arr, n);
58
59 puts("Sorted Array ");
60 printArray(arr, n);
61
62 return 0;
63 }

相關推薦

經典演算法:烙餅排序

原理非常簡單,看視訊即可 給一個為排序的陣列,你只能再改對該陣列做如下操作:flip(arr, i): 將陣列arr[0...i]進行逆置。如何對該陣列進行排序? 這個問題在程式設計之美一書也有提及: 星期五的晚上,一幫同事在希格瑪大廈附近的“硬碟酒吧”多喝了幾杯。程式設

經典演算法:希爾排序的實現

希爾排序我感覺並沒有什麼用 = =因為希爾排序事實上是對插入排序的一個複雜化,在插入排序的基礎上引入了一種分組機制,所以這種排序事實上是複雜了。 並且這種排序和插入排序的實現機制非常相似,只要稍微增加

NOJ1002演算法實驗一分治演算法歸併排序

1002.歸併排序 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 給定一個數列,用歸併排序演算法把它排成升序。 輸入 第一行是一個整數n(n不大於10000),表示要排序的數的個數; 下面一行是用空格隔開的n個整數。 輸出

C++演算法選擇排序

#include <iostream> using namespace std; void myswap2(int &a, int &b) { int temp = b;

經典演算法:BFS與DFS

寫在最前的三點: 1、所謂圖的遍歷就是按照某種次序訪問圖的每一頂點一次僅且一次。 2、實現bfs和dfs都需要解決的一個問題就是如何儲存圖。一般有兩種方法:鄰接矩陣和鄰接表。這裡為簡單起 見,均採用鄰接矩陣儲存,說白了也就是二維陣列。 3、本文章的小測試部分的測試例項

經典演算法:如何判斷整數和浮點數是否相等

這個問題來自於我解決一個叫做五猴分桃的問題 其中會出現這麼一些資料 我需要在右邊第二欄資料裡面找到整數型的資料,比如說 3121這類的資料 但是我給第二欄定義的是float型的資料,如何判斷這個float型的資料是不是整數呢? 用瞭如下方法,注意看!

經典演算法: 羅馬數字

關於羅馬數字,一到10可以介紹給大家一個簡單的記法 I 代表 1 V 代表 5 X 代表 10 4 9 特殊記 在 V 和 X 的左邊放一個 I 代表減去 1 thus : 4 —>

經典演算法:關於大小寫的轉換問題

tips: 知道一點即可,所有字元都是0-255之間的值,所以大小寫的轉換隻需要對其進行數值上面的加減運算就可以了 小寫字母的值比大寫字母的值大32 展示一個程式碼: 這個就可以把a轉換為大A,

經典演算法——KMP,深入講解next陣列的求解

前言     之前對kmp演算法雖然瞭解它的原理,即求出P0···Pi的最大相同前後綴長度k;但是問題在於如何求出這個最大前後綴長度呢?我覺得網上很多帖子都說的不是很清楚,總感覺沒有把那層紙戳破,後來翻看演算法導論,32章 字串匹配雖然講到了對前字尾計算的正確性,但是大量的推理證明不大好理解,沒有與程式結合

經典演算法:愛因斯坦臺階問題

愛因斯坦臺階問題 愛因斯坦曾經提出過這樣一道有趣的數學題:有一個長階梯,若每步上2階,最後剩下1階;若每步上3階,最後剩2階;若每步上5階,最後剩下4階;若每步上6階,最後剩5階;只有每步上7階,最後剛好一階也不剩。請問該階梯至少有多少階。 解題思路 不是

經典演算法:把String變為double型的方法

題目 如題,假設資料為:63.2558的string型別,如何把它變為double型 處理辦法 直接細節入手,前面先找到前置位,後面找到後置位,都是一些普通的辦法,然後把它一起加起來,最後就得到

分治演算法歸併排序,快速排序和漢諾塔

1介紹 分治演算法已經是本人所寫的常用算法系列的第三個了,可能只會寫這一節,對比動態規劃與貪心演算法我們來認識一下分治演算法。 從思路上來看: (1)動態規劃:多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解。每一個階段的最優解是基於前一個階段的最優解。

經典演算法:蛇形填數,最簡單的方法了。。。

問題概述 什麼是蛇形填數,百度一下即可 解法 你能發現這裡面的數為1到 n*n; 所以寫個迴圈即可 while(count<n*n){ while(x+1&l

經典演算法:Dijskstra演算法與Floyd演算法

 Dijkstra演算法利用的是一個經典的東西,叫做保持好的最短路徑,目的就是為了在尋找最短路徑的時候的保持最短化的過程 Floyd演算法利用的是一個經典的公式  D[I,J]>D[I,K] + D[K,J]  則  D[I J] = D[I K] + D[K J]

經典排序演算法八大排序對比總結

針對前面討論的八大經典排序演算法:氣泡排序、插入排序、選擇排序、堆排序、歸併排序、快速排序、希爾排序、桶排序。 關於各種什麼時間複雜度,空間複雜度的對比總結,網上一大堆,別人也總結的很好,這裡就不贅述了,這裡主要通過對大量資料進行排序測試,測試各排序演算法的執行時間,來比較

排序演算法選擇排序(Selection sort)

  0. 說明   選擇排序(Selection sort)是一種簡單直觀的排序演算法。   它的工作原理如下。   首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完

資料結構與演算法插入排序

 插入排序是演算法中的基礎入門和氣泡排序、選擇排序都是必要掌握的。他們都是對比排序,需要通過比較大小交換位置,進行排序。 插入排序的實現思路: 1、 從第一個元素開始,這個元素可以認為已經被排序。 2、取出下一個元素,在已排序的序列中從後往前掃描。 3、如果該元素小於小於前

資料結構與演算法 ---快速排序

快速排序流程: 1.從數列中挑出一個基準值 2.將所有比基準值小的擺放在基準前面,所有比基準值大的擺在後面(相同的數可以放到任一邊);在這個分割槽退出之後,該基準就處於數列的中間位置。 3.遞迴地把“基準值前面的子數列”和“基準值後面的子數列”進行排序。   下面以數列

資料結構與演算法------氣泡排序

 學習開發一年的時間裡,很少去了解排序演算法,氣泡排序也是最開始學習的樣子,靠死記硬背,沒有引入自己的理解。  對於什麼時間複雜度和空間複雜度和穩定性也不清楚其原委,或許在程式碼方面少了幾許的天分: 氣泡排序: 氣泡排序每一輪的比較都是前面的數和後面的數進行比較,並交

一起學習排序演算法氣泡排序

氣泡排序 Bubble sort 本系列的文章列表和相關說明,請檢視【一起學習排序演算法】0.序言 也可以直接到github上檢視完整的文章和原始碼! 原理 先看看Wikipedia的定義: Bubble sort is a simple sorting algorithm that