Day 23 資料結構模組deque:旁人來來去去像行雲流水
註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10247295
先來解一下上次的練習吧!
我們唯一需要動的應該只有calculate的函式,
當 p1 < p2 時,將兩個值交換即可。
別忘了交換應該要連同Entry裡面的值都一起換(price1/price2)。
| |
我們今天要來談談deque的應用,
我們前面已經在第十一篇的部分提到過deque的用法,這篇主要要來補充deque作為queue時的常見狀況。
一般我們提到兩種資料結構:
queue(佇列)或stack(堆疊)的概念,
其實就是先進先出(FIFO, First-In-First-Out)或
先進後出(First-In-Last-Out)的區別。
queue就好像排隊一樣,當然是先排的先被服務到(除非有人插隊XD);
stack則像是一疊文件一樣,假設你都拿最上面的,
當老闆又往上放新的文件(工作)給你的時候,
你再拿就會拿到最新放上去的囉!
這兩者在不同的程式語言有時候會有不同的稱呼和變形,
但本質是不變的。
那麼,什麼狀況下我們寫程式會容易用到queue(deque)呢?
最常見的狀況是遇到一個Tree(樹)的問題的時候!
那,什麼是樹呢?
好問題!這個問題應該要用比較長的篇幅解釋,
所以請讀者參閱拙作從LeetCode學演算法的第十四篇,
下面我們再繼續。
不囉嗦,我們直接上一道題目作為範例吧!
上面的連結應該已經介紹過二元樹了,
最簡單來說,一棵二元樹就是由根節點(root),
及左子樹(left tree)/右子樹(right tree)所構成。
每個節點上有可能連結左右節點,
也可能沒有連接,稱為NIL,在Python為None。
如果我們今天想要按照一層一層順序來走遍整個樹,
並分層記錄的話,該怎麼做呢?
這個問題通常被稱為Level-order Traversal。(層序遍歷)
讀者可以前往LeetCode的題目看更詳細的描述。
https://leetcode.com/problems/binary-tree-level-order-traversal/
我們可以先走第一層,再走第二層,以此類推,
那麼這中間走完第一層時,怎麼知道第二層有哪些節點呢?
按順序的話,我們應該將第一層的每個節點的左節點/右節點,
放入到一個可以按照放入的順序處理的資料結構,
接著再從這個資料結構裡一個一個拿出來(這時候是第二層了!),
找每一個的左右節點,再放進去……
咦?這個資料結構不就是queue嗎XD?
我們在解題和寫程式的時候,
可以先把要怎麼做大略寫出來,
再根據這個概念和做法,寫出具體的程式。
以這個問題來說,
題目應該會給出這個二元樹的根節點root,
接著要做的事情就如上面說的一樣,但我們需要一些細部的東西:
- 開一個res(result)作為存放答案用的串列。
- 我們先檢查root是否存在,有些題目壞壞的會給None,
如果不存在就直接回傳空的答案給它! - 將root放入我們檢查的資料結構(因為它是第一層),我們先叫它q吧!
- 開始一個迴圈,當q裡面還有節點時,代表還要繼續。
- 我們先記下q裡面的個數(命名為cnt),後面放進去q的都是下一層的節點。
- 接著先設定一個level變數,用以記錄這層的節點值們。
- 在裡面再開一個迴圈,這次直接指定跑cnt次,
這樣所有這層的節點都會被我們取出來。 - 內層迴圈中,每次從q取出一個節點(popleft),
將節點值(.value)append到level中, - 檢查左節點,如果不是None的話就將節點放到q裡。
- 檢查右節點,做相同的事情XD
- 內層迴圈結束後,這時候我們拿到一整層的節點值,
我們應該要將其append到res這個結果裡。 - 最後全部處理完後,可以將res回傳。
好啦!經過上面的步驟,有沒有發現我們其實已經把程式寫完了呢?
只要按著順序對照,應該可以順利寫出答案。
那麼,我們就來看看實際的做法:
| |
| |
| |
應該不算太難(吧)…?
請務必要看完樹的那篇定義再來看這篇喲!
總言之,deque作為queue使用時,主要會用popleft()跟append()來操作,
同時它會適合按先後順序放入及取出的情況。
練習題目的話,
讀者可以再嘗試看看LeetCode的另一題:
101. Symmetric Tree
那麼,我們就明天見囉!
工商時間:
抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
在Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」
超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!
期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)
容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享 ,及訪談國內外不同經驗的工程師 ,
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作 ,
是初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」 :
https://bit.ly/advleetcode
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/allleetcode
