燒餅排序

讀完本文概说,你可以去力扣拿下如下題目:

969.煎餅排序

-----------

燒餅排序是個很有意思的實際問題:假設(shè)盤子上有 n面積大小不一的燒餅剩胁,你如何用一把鍋鏟進行若干次翻轉(zhuǎn)声旺,讓這些燒餅的大小有序(小的在上斧拍,大的在下)己儒?

image

設(shè)想一下用鍋鏟翻轉(zhuǎn)一堆燒餅的情景记焊,其實是有一點限制的芳杏,我們每次只能將最上面的若干塊餅子翻轉(zhuǎn):

image

我們的問題是,如何使用算法得到一個翻轉(zhuǎn)序列抡柿,使得燒餅堆變得有序舔琅?

首先,需要把這個問題抽象洲劣,用數(shù)組來表示燒餅堆:

image

如何解決這個問題呢备蚓?其實類似上篇文章 遞歸反轉(zhuǎn)鏈表的一部分,這也是需要遞歸思想的囱稽。

PS:我認真寫了 100 多篇原創(chuàng)郊尝,手把手刷 200 道力扣題目,全部發(fā)布在 labuladong的算法小抄战惊,持續(xù)更新流昏。建議收藏,按照我的文章順序刷題,掌握各種算法套路后投再入題海就如魚得水了况凉。

一谚鄙、思路分析

為什么說這個問題有遞歸性質(zhì)呢?比如說我們需要實現(xiàn)這樣一個函數(shù):

// cakes 是一堆燒餅刁绒,函數(shù)會將前 n 個燒餅排序
void sort(int[] cakes, int n);

如果我們找到了前 n 個燒餅中最大的那個襟锐,然后設(shè)法將這個餅子翻轉(zhuǎn)到最底下:

image

那么,原問題的規(guī)模就可以減小膛锭,遞歸調(diào)用 pancakeSort(A, n-1) 即可:

image

接下來,對于上面的這 n - 1 塊餅蚊荣,如何排序呢初狰?還是先從中找到最大的一塊餅,然后把這塊餅放到底下互例,再遞歸調(diào)用 pancakeSort(A, n-1-1)……

你看奢入,這就是遞歸性質(zhì),總結(jié)一下思路就是:

1媳叨、找到 n 個餅中最大的那個腥光。

2、把這個最大的餅移到最底下糊秆。

3武福、遞歸調(diào)用 pancakeSort(A, n - 1)

base case:n == 1 時痘番,排序 1 個餅時不需要翻轉(zhuǎn)捉片。

那么,最后剩下個問題汞舱,如何設(shè)法將某塊燒餅翻到最后呢伍纫?

其實很簡單,比如第 3 塊餅是最大的昂芜,我們想把它換到最后莹规,也就是換到第 n 塊∶谏瘢可以這樣操作:

1良漱、用鍋鏟將前 3 塊餅翻轉(zhuǎn)一下,這樣最大的餅就翻到了最上面腻扇。

2债热、用鍋鏟將前 n 塊餅全部翻轉(zhuǎn),這樣最大的餅就翻到了第 n 塊幼苛,也就是最后一塊窒篱。

以上兩個流程理解之后,基本就可以寫出解法了,不過題目要求我們寫出具體的反轉(zhuǎn)操作序列墙杯,這也很簡單配并,只要在每次翻轉(zhuǎn)燒餅時記錄下來就行了。

二高镐、代碼實現(xiàn)

只要把上述的思路用代碼實現(xiàn)即可溉旋,唯一需要注意的是,數(shù)組索引從 0 開始嫉髓,而我們要返回的結(jié)果是從 1 開始算的观腊。

// 記錄反轉(zhuǎn)操作序列
LinkedList<Integer> res = new LinkedList<>();

List<Integer> pancakeSort(int[] cakes) {
    sort(cakes, cakes.length);
    return res;
}

void sort(int[] cakes, int n) {
    // base case
    if (n == 1) return;
    
    // 尋找最大餅的索引
    int maxCake = 0;
    int maxCakeIndex = 0;
    for (int i = 0; i < n; i++)
        if (cakes[i] > maxCake) {
            maxCakeIndex = i;
            maxCake = cakes[i];
        }
    
    // 第一次翻轉(zhuǎn),將最大餅翻到最上面
    reverse(cakes, 0, maxCakeIndex);
    res.add(maxCakeIndex + 1);
    // 第二次翻轉(zhuǎn)算行,將最大餅翻到最下面
    reverse(cakes, 0, n - 1);
    res.add(n);

    // 遞歸調(diào)用
    sort(cakes, n - 1);
}

void reverse(int[] arr, int i, int j) {
    while (i < j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        i++; j--;
    }
}

通過剛才的詳細解釋梧油,這段代碼應(yīng)該是很清晰了。

算法的時間復雜度很容易計算州邢,因為遞歸調(diào)用的次數(shù)是 n儡陨,每次遞歸調(diào)用都需要一次 for 循環(huán),時間復雜度是 O(n)量淌,所以總的復雜度是 O(n^2)骗村。

最后,我們可以思考一個問題?:按照我們這個思路呀枢,得出的操作序列長度應(yīng)該為? 2(n - 1)胚股,因為每次遞歸都要進行 2 次翻轉(zhuǎn)并記錄操作,總共有 n 層遞歸硫狞,但由于 base case 直接返回結(jié)果信轿,不進行翻轉(zhuǎn),所以最終的操作序列長度應(yīng)該是固定的 2(n - 1)残吩。

顯然财忽,這個結(jié)果不是最優(yōu)的(最短的),比如說一堆煎餅 [3,2,4,1]泣侮,我們的算法得到的翻轉(zhuǎn)序列是 [3,4,2,3,1,2]即彪,但是最快捷的翻轉(zhuǎn)方法應(yīng)該是 [2,3,4]

初始狀態(tài) :[3,2,4,1]
翻前 2 個:[2,3,4,1]
翻前 3 個:[4,3,2,1]
翻前 4 個:[1,2,3,4]

如果要求你的算法計算排序燒餅的最短操作序列,你該如何計算呢活尊?或者說隶校,解決這種求最優(yōu)解法的問題,核心思路什么蛹锰,一定需要使用什么算法技巧呢深胳?

不妨分享一下你的思考。

_____________

我的 在線電子書 有 100 篇原創(chuàng)文章铜犬,手把手帶刷 200 道力扣題目舞终,建議收藏轻庆!對應(yīng)的 GitHub 算法倉庫 已經(jīng)獲得了 70k star,歡迎標星敛劝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末余爆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子夸盟,更是在濱河造成了極大的恐慌蛾方,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件上陕,死亡現(xiàn)場離奇詭異桩砰,居然都是意外死亡,警方通過查閱死者的電腦和手機释簿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門五芝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辕万,你說我怎么就攤上這事〕辽荆” “怎么了渐尿?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矾瑰。 經(jīng)常有香客問我砖茸,道長,這世上最難降的妖魔是什么殴穴? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任凉夯,我火速辦了婚禮,結(jié)果婚禮上采幌,老公的妹妹穿的比我還像新娘劲够。我一直安慰自己,他們只是感情好休傍,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布征绎。 她就那樣靜靜地躺著,像睡著了一般磨取。 火紅的嫁衣襯著肌膚如雪人柿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天忙厌,我揣著相機與錄音凫岖,去河邊找鬼。 笑死逢净,一個胖子當著我的面吹牛哥放,可吹牛的內(nèi)容都是我干的歼指。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼婶芭,長吁一口氣:“原來是場噩夢啊……” “哼东臀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起犀农,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤惰赋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后呵哨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赁濒,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年孟害,在試婚紗的時候發(fā)現(xiàn)自己被綠了拒炎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡挨务,死狀恐怖击你,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谎柄,我是刑警寧澤丁侄,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站朝巫,受9級特大地震影響鸿摇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜劈猿,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一拙吉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揪荣,春花似錦筷黔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揽乱,卻和暖如春名眉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凰棉。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工损拢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撒犀。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓福压,卻偏偏與公主長得像掏秩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子荆姆,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容