<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tree on 跟著 Desolve 學程式</title><link>https://desolve.pages.dev/tags/tree/</link><description>Recent content in Tree on 跟著 Desolve 學程式</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Tue, 21 Sep 2021 00:00:00 +0800</lastBuildDate><atom:link href="https://desolve.pages.dev/tags/tree/index.xml" rel="self" type="application/rss+xml"/><item><title>從LeetCode學演算法 - 116 Tree (21) / DFS (19)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/</link><pubDate>Tue, 21 Sep 2021 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 116 Tree (21) / DFS (19)" /&gt;&lt;p&gt;&lt;strong&gt;0814. Binary Tree Pruning (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;(基礎+進階+面試篇) 從 LeetCode 學演算法 + 面試成功指南**&lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
&gt;http://bit.ly/zeroclg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;新書(第一本，不曉得會不會是最後一本XD)開始預購啦！&lt;br&gt;
&lt;strong&gt;初學 Python 的第一本書 : 從基本語法到模組應用（iT邦幫忙鐵人賽系列書）&lt;/strong&gt; &lt;a class="link" href="https://www.tenlong.com.tw/products/9789864348503" target="_blank" rel="noopener"
&gt;https://www.tenlong.com.tw/products/9789864348503&lt;/a&gt;&lt;br&gt;
這本書主要是針對初學Python的入門讀者，希望能夠提供一個得以從零開始上手，又不會太過冗長的入門學習書。有興趣的話請多多支持！&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given the &lt;code&gt;root&lt;/code&gt; of a binary tree, return &lt;em&gt;the same tree where every subtree (of the given tree) not containing a&lt;/em&gt; &lt;code&gt;1&lt;/code&gt; &lt;em&gt;has been removed&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A subtree of a node &lt;code&gt;node&lt;/code&gt; is &lt;code&gt;node&lt;/code&gt; plus every node that is a descendant of &lt;code&gt;node&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz.png"
width="800"
height="224"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz_hu_3229419e65641c69.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz_hu_9fe37af931d61d84.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="357"
data-flex-basis="857px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,null,0,0,1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,null,0,null,1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Only the red nodes satisfy the property &amp;#34;every subtree not containing a 1&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The diagram on the right represents the answer.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU.png"
width="800"
height="184"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU_hu_f177f01d2062f25e.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU_hu_e46343ca46cdc39a.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="434"
data-flex-basis="1043px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,0,1,0,0,0,1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,null,1,null,1]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x.png"
width="800"
height="215"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x_hu_cb5bd4c11095c465.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x_hu_960d09212f347a67.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="372"
data-flex-basis="893px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,1,0,1,1,0,1,0]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,1,0,1,1,null,1]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;The number of nodes in the tree is in the range &lt;code&gt;[1, 200]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.val&lt;/code&gt; is either &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹的root，將同一棵樹中未含任何1的子樹均去除掉並回傳。&lt;br&gt;
(限制條件：樹的節點數目在1~200之間，且Node的值只會是0或1)&lt;/p&gt;
&lt;p&gt;如果我們看到範例的話，大致上可以理解要被去掉的部分就是包括自己以及其底下的所有節點值均為0的子樹，這樣才能保證剩下的符合題目要求的條件。&lt;/p&gt;
&lt;p&gt;因此，我們總體要做的就是檢查一棵樹的左子樹及右子樹狀況，&lt;br&gt;
然後分別決定左子樹/右子樹是否要被去掉，最後將當棵樹的總體狀況往上回傳，因此，設計一個子函數helper如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;傳入要檢查的節點n&lt;/li&gt;
&lt;li&gt;如果n是空節點，則直接回傳0(因為這代表往下左右沒有其它節點了，也不用繼續檢查)&lt;/li&gt;
&lt;li&gt;遞迴檢查左子樹(將n.left代入helper)，取得左子樹含1的節點數量為l&lt;/li&gt;
&lt;li&gt;遞迴檢查右子樹(將n.right代入helper)，取得右子樹含1的節點數量為r&lt;/li&gt;
&lt;li&gt;若l為0，表示無左子樹或左子樹均無節點值為1的節點，將n.left設為NIL&lt;/li&gt;
&lt;li&gt;同理，若r為0，將n.right設為NIL&lt;/li&gt;
&lt;li&gt;回傳l+r+n.val&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在將root代入helper遞迴結束後，所有root的子樹應該都被清乾淨了，&lt;br&gt;
除了root自己以外，所以我們要檢查helper得到的最後的值，&lt;br&gt;
若為0的話，則最終我們應回傳NIL，否則應回傳root。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分使用三元運算子來處理最後的c，&lt;br&gt;
其實我們也可以將整個helper的函式使用True/False來處理，&lt;br&gt;
這樣中間的計算就要改成or來檢查是否至少存在一個節點值為1的節點。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/e76ff62f67e0540792c41c7ae6b3fa6e.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分使用子函數來簡單處理，其它的部分邏輯一樣。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/6ebdc845996a04c178cd6a6e2c727b1b.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(N)，N為節點總數，總體的遞迴深度則和樹的高度一致。)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 108 Tree (20) / DFS (17)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/</link><pubDate>Sun, 03 Jan 2021 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 108 Tree (20) / DFS (17)" /&gt;&lt;p&gt;&lt;strong&gt;1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;好久不見！筆者最近剛換了工作，&lt;br&gt;
所以比較忙一點XD &lt;strong&gt;之後1月中會有HiSKIO 技術年貨節的活動，&lt;br&gt;
歡迎大家拿著折價券來修從LeetCode學演算法的課程喲！&lt;br&gt;
如果預算不夠，相信這108篇也還是很夠讀者練習的啦XDD&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在更之後還有規劃0元挑戰賽的部分，&lt;br&gt;
只要&lt;strong&gt;修課後一定時間內成功錄取新工作&lt;/strong&gt; ，&lt;br&gt;
&lt;strong&gt;課程就會全額退費喲！&lt;/strong&gt; 這部分再請留意官方那邊的公告，&lt;br&gt;
如果有開始的話，文章中也會再提醒各位。&lt;/p&gt;
&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong&gt;&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeall&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given two binary trees &lt;code&gt;original&lt;/code&gt; and &lt;code&gt;cloned&lt;/code&gt; and given a reference to a node &lt;code&gt;target&lt;/code&gt; in the original tree.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cloned&lt;/code&gt; tree is a &lt;strong&gt;copy of&lt;/strong&gt; the &lt;code&gt;original&lt;/code&gt; tree.&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;a reference to the same node&lt;/em&gt; in the &lt;code&gt;cloned&lt;/code&gt; tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that you are ** not allowed** to change any of the two trees or the &lt;code&gt;target&lt;/code&gt; node and the answer ** must be** a reference to a node in the &lt;code&gt;cloned&lt;/code&gt; tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt; Solve the problem if repeated values on the tree are allowed.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM.png"
width="544"
height="426"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM_hu_7f4c691b13b758ac.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM_hu_de7dc142adc071cf.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="127"
data-flex-basis="306px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: tree = [7,4,3,null,null,6,19], target = 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: In all examples the original and cloned trees are shown. The target node is a green node from the original tree. The answer is the yellow node from the cloned tree.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK.png"
width="221"
height="159"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK_hu_fe0d5df90720a9ca.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK_hu_826cf7448e681926.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="138"
data-flex-basis="333px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: tree = [7], target = 7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq.png"
width="459"
height="486"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq_hu_76be706ea408d602.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq_hu_4f4752dc72bf39a3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="94"
data-flex-basis="226px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: tree = [8,null,6,null,5,null,4,null,3,null,2,null,1], target = 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-4"&gt;Example 4
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel.png"
width="800"
height="344"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel_hu_d69dcd8ac08765e7.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel_hu_8fd282df5ba1d125.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="232"
data-flex-basis="558px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: tree = [1,2,3,4,5,6,7,8,9,10], target = 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-5"&gt;Example 5
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2.png"
width="427"
height="345"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2_hu_202c81a68a227443.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2_hu_fe1e7fc89f94a0a2.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="123"
data-flex-basis="297px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: tree = [1,2,null,3], target = 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;The number of nodes in the &lt;code&gt;tree&lt;/code&gt; is in the range &lt;code&gt;[1, 10^4]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The values of the nodes of the &lt;code&gt;tree&lt;/code&gt; are unique.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;target&lt;/code&gt; node is a node from the &lt;code&gt;original&lt;/code&gt; tree and is not &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定兩個二元樹 original 跟 cloned ，&lt;br&gt;
並給定一個 originl 樹上的參考節點 target，&lt;br&gt;
當中，cloned是original的完全複製，&lt;br&gt;
請找到 cloned 上和 target 相對應的相同節點回傳。&lt;br&gt;
留意兩棵樹上的節點都不允許被改變，&lt;br&gt;
且答案必須要是cloned這棵樹上的對應節點。&lt;br&gt;
(而不是original上的或新作出來的節點)&lt;/p&gt;
&lt;p&gt;條件限制：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;樹上的總節點數量範圍在1到10⁴之間。&lt;/li&gt;
&lt;li&gt;樹上的各節點值均為&lt;strong&gt;獨一無二&lt;/strong&gt; 的。&lt;/li&gt;
&lt;li&gt;target是original這棵樹上的節點，且不為null。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;後續：如果重複值可被允許，嘗試在這個條件下解決問題。&lt;/p&gt;
&lt;p&gt;這題雖然標為Medium，但說實在的不難XD&lt;br&gt;
看完題目以後，已經經歷過前面各種難題的讀者，&lt;br&gt;
應該會直覺想到使用DFS來解決。&lt;/p&gt;
&lt;p&gt;那麼，由於題目一開始已經給定說值是全部獨一無二。&lt;br&gt;
如果先不計較Follow up的部分，&lt;br&gt;
其實我們可以直接比較值就可以了！&lt;br&gt;
我們可以直接將target的值當作目標，&lt;br&gt;
並且對於cloned這棵樹進行dfs，只要比較到相同的值，&lt;br&gt;
就可以進行回傳啦！&lt;br&gt;
由於1的關係，我們不用擔心使用遞迴會超過call stack限制，&lt;br&gt;
使用一個helper函式，當遇到null/None時，&lt;br&gt;
回傳null/None，接著&lt;strong&gt;檢查所在節點值是否和target的值相同&lt;/strong&gt; ；&lt;br&gt;
接著分別&lt;strong&gt;dfs往左邊和往右邊的樹進行尋找&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;當&lt;strong&gt;左邊已經找到時，我們可以不用再檢查右邊的部分&lt;/strong&gt; ，&lt;br&gt;
直接回傳得到的節點；否則&lt;strong&gt;當右邊有找到時，回傳右邊得到的節點&lt;/strong&gt; ；&lt;br&gt;
&lt;strong&gt;當右邊也沒有找到時，則回傳null/None&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;那麼，如果節點值不一定獨一無二呢？&lt;br&gt;
那麼我們就要同時也將original一起進行遞迴，&lt;br&gt;
這時候檢查的就是original上歷經的節點是否是target節點，&lt;br&gt;
在檢查到的時候同時去回傳cloned的對應節點。&lt;/p&gt;
&lt;p&gt;這時候我們&lt;strong&gt;用來檢查相等的就是記憶體位址，而非節點值&lt;/strong&gt; 。&lt;br&gt;
因為唯有記憶體位址相同時，能保證這個節點是對應位置的那個節點。&lt;br&gt;
(而非只有裡面的值相同)&lt;/p&gt;
&lt;p&gt;依此，我們寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分我們額外提供了LeetCode上Follow Up的解法在註解，&lt;br&gt;
使用相同的做法，應該也可以寫出Python的方法，&lt;br&gt;
讀者可以自行嘗試看看。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/af0e4cf14db21baf15da0e10aa9b4121.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分，請讀者留意，&lt;br&gt;
對Python而言，我們寫n: TreeNode, v: int這樣的格式，&lt;br&gt;
是&lt;strong&gt;寫給人看的&lt;/strong&gt; XD，讀者也可以完全都不寫，一樣可以執行。&lt;br&gt;
而且對於使用者來說，就算你將v代成不是int的東西，&lt;br&gt;
也不會直接被Python視為錯誤，&lt;br&gt;
並不像Java或其他程式語言那樣對這邊有型別檢查，&lt;br&gt;
這點請務必留意喲！&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/dd29c995eb91cf5776d22c618eed221d.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，基本上最差的狀況要遍歷整棵樹，&lt;br&gt;
而空間上要計較Call Stack的話，則會跟樹的深度成正比，&lt;br&gt;
除此以外沒有其他額外和N相關的部分)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 106 Tree (19) / DFS (16)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/</link><pubDate>Mon, 09 Nov 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 106 Tree (19) / DFS (16)" /&gt;&lt;p&gt;&lt;strong&gt;0563. Binary Tree Tilt (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong&gt;&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeall&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given the &lt;code&gt;root&lt;/code&gt; of a binary tree, return &lt;em&gt;the sum of every tree node&amp;rsquo;s&lt;/em&gt; *&lt;strong&gt;tilt&lt;/strong&gt; *&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;tilt&lt;/strong&gt; of a tree node is the ** absolute difference** between the sum of all left subtree node ** values** and all right subtree node ** values**. If a node does not have a left child, then the sum of the left subtree node ** values** is treated as &lt;code&gt;0&lt;/code&gt;. The rule is similar if there the node does not have a right child.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-.jpg"
width="712"
height="182"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-_hu_f8f0e2bb9975a20e.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-_hu_fa6cedeb906b0062.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="391"
data-flex-basis="938px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 2 : |0-0| = 0 (no children)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 3 : |0-0| = 0 (no children)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tile of node 1 : |2-3| = 1 (left subtree is just left child, so sum is 2; right subtree is just right child, so sum is 3)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sum of every tilt : 0 + 0 + 1 = 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC.jpg"
width="800"
height="203"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC_hu_1f4637af595424cb.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC_hu_fe4828eaf0547edf.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="394"
data-flex-basis="945px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [4,2,9,3,5,null,7]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 15
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 3 : |0-0| = 0 (no children)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 5 : |0-0| = 0 (no children)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 7 : |0-0| = 0 (no children)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 2 : |3-5| = 2 (left subtree is just left child, so sum is 3; right subtree is just right child, so sum is 5)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 9 : |0-7| = 7 (no left child, so sum is 0; right subtree is just right child, so sum is 7)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tilt of node 4 : |(3+5+2)-(9+7)| = |10-16| = 6 (left subtree values are 3, 5, and 2, which sums to 10; right subtree values are 9 and 7, which sums to 16)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sum of every tilt : 0 + 0 + 0 + 2 + 7 + 6 = 15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l.jpg"
width="800"
height="293"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l_hu_844a577989e5bf4a.jpg 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l_hu_34b639756e8b7f75.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="273"
data-flex-basis="655px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [21,7,14,1,1,2,2,3,3]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;The number of nodes in the tree is in the range &lt;code&gt;[0, 104]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-1000 &amp;lt;= Node.val &amp;lt;= 1000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，試計算二元樹的每個節點的tilt(坡度)和。&lt;/p&gt;
&lt;p&gt;什麼是tilt呢?&lt;br&gt;
題目告訴我們，對於一個節點，&lt;br&gt;
其左子樹的和以及右子樹的和相減的絕對值，&lt;br&gt;
就稱為它的坡度(tilt)，當子樹不存在時，和則視為0。&lt;/p&gt;
&lt;p&gt;另外由於整個樹的總節點數已經被限定在0~104之間了，&lt;br&gt;
表示我們可以放心的用遞迴！&lt;/p&gt;
&lt;p&gt;那麼，我們該怎麼對每個節點算坡度呢？&lt;br&gt;
對於一個節點n，如果它不存在的話(NIL)，&lt;br&gt;
&lt;strong&gt;其坡度自然為0，且總和同樣為0&lt;/strong&gt; ；&lt;br&gt;
存在的話，我們必須先算出&lt;strong&gt;左子樹(n.left為根節點的子樹)和，&lt;br&gt;
以及右子樹(n.right為根節點的子樹)和，將兩者相減取絕對值，&lt;br&gt;
就是n的坡度。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因此，我們可以使用一個dfs的函式來同時處理算子樹和，&lt;br&gt;
以及坡度的部分，整個dfs的概念應該會如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;若n為NIL，回傳0&lt;/li&gt;
&lt;li&gt;將n.left代入dfs中，取得n.left的子樹和l&lt;/li&gt;
&lt;li&gt;將n.right代入dfs中，取得n.right子樹和r&lt;/li&gt;
&lt;li&gt;將|l-r|加到物件變數的答案res中&lt;/li&gt;
&lt;li&gt;回傳l+r+n.val&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;留意到我們使用dfs的回傳一直都是回傳以n為根節點的子樹和，&lt;br&gt;
這個和我們要計算的坡度不同，所以必須要用一個res變數來儲存。&lt;/p&gt;
&lt;p&gt;在寫出dfs函式後，我們只需要初始化res，&lt;br&gt;
並且在主函式中呼叫dfs後，回傳res即可。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java-對於java而言abs在javalangmath函式庫中"&gt;Java 對於Java而言abs在java.lang.Math函式庫中，
&lt;/h3&gt;&lt;p&gt;如果不是在LeetCode的編輯器的話，不要忘記自行import。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/e737e1f9dd68f2eca0b6352f790fb0a9.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分和Java大同小異，&lt;br&gt;
這邊採用將dfs寫成一個子函式，別忘記要宣告以後才能夠使用呦！&lt;br&gt;
此外，__init__並非一定要這樣使用，在class Solution中直接定義也沒問題。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/5420e6680c86b99d7f00c51bb3b55430.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(樹的深度)，最差則為O(N))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 105 Tree (18) / DFS (15) / Backtracking (7)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-105-tree-18-dfs-15-backtracking-7/</link><pubDate>Mon, 14 Sep 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-105-tree-18-dfs-15-backtracking-7/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 105 Tree (18) / DFS (15) / Backtracking (7)" /&gt;&lt;p&gt;&lt;strong&gt;0437. Path Sum III (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;容筆者工商一下， &lt;strong&gt;「從Leetcode學演算法｜進階篇」及&lt;/strong&gt; 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p&gt;
&lt;p&gt;目前只剩下給讀者的&lt;strong&gt;進階篇+面試篇(3150)&lt;/strong&gt; 和&lt;strong&gt;全套同捆優惠(3990)&lt;/strong&gt; 了QQ&lt;br&gt;
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;br&gt;
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeall&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;內容介紹：&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;/p&gt;
&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;You are given a binary tree in which each node contains an integer value.&lt;/p&gt;
&lt;p&gt;Find the number of paths that sum to a given value.&lt;/p&gt;
&lt;p&gt;The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).&lt;/p&gt;
&lt;p&gt;The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5 -3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3 2 11
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3 -2 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Return 3. The paths that sum to 8 are:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. 5 -&amp;gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. 5 -&amp;gt; 2 -&amp;gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. -3 -&amp;gt; 11
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;給定一個二元樹，當中每個節點均含一個整數，&lt;br&gt;
找出所有可以加總等於目標總和的路徑數量。&lt;br&gt;
一個路徑不需要從根節點開始，也不必一定要到葉節點結束，&lt;br&gt;
但是路徑只能往下走(也就是說只能從父節點往子節點走)；&lt;br&gt;
另外，這棵樹最多只會有1000個節點，&lt;br&gt;
且其值均在-1000000~1000000之間。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;這一題是一整組Path Sum系列題的第三題。&lt;br&gt;
由於題目提示節點數不會超過1000個，&lt;br&gt;
所以基本是無法超過各程式的Call Stack限制，可以放心使用遞迴。&lt;/p&gt;
&lt;p&gt;那麼，我們看看另一個重點：&lt;br&gt;
路徑只能往下走，會有什麼特點呢？&lt;br&gt;
舉例來說，以上面的二元樹，當我們走到某個節點2時，&lt;br&gt;
所有終點是2的路徑有以下三種：&lt;br&gt;
10 -&amp;gt; 5 -&amp;gt; 2 &lt;br&gt;
5 -&amp;gt; 2&lt;br&gt;
2&lt;br&gt;
再往下走到1的時候，路徑有以下四種：&lt;br&gt;
&lt;strong&gt;10 -&amp;gt; 5 -&amp;gt; 2&lt;/strong&gt; -&amp;gt; 1&lt;br&gt;
&lt;strong&gt;5 -&amp;gt; 2&lt;/strong&gt; -&amp;gt; 1&lt;br&gt;
&lt;strong&gt;2&lt;/strong&gt; -&amp;gt; 1&lt;br&gt;
1&lt;/p&gt;
&lt;p&gt;我們可以發現，走到1的路徑和到底有沒有符合target的解這件事情，&lt;br&gt;
可以透過兩點知道：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;從root起算走到現在這個節點的總和是否和target相等&lt;/li&gt;
&lt;li&gt;從root起算走到現在這個節點的總和-target是否在過往出現過&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第2點比較抽象，我們稍微舉一下簡單的例子：&lt;br&gt;
假設我們要找的目標是8的話，&lt;br&gt;
那麼直接看我們當然知道是5-&amp;gt;2-&amp;gt;1，&lt;br&gt;
但如果不能回頭重算的話，要怎麼辦呢？&lt;br&gt;
&lt;strong&gt;我們可以得到5-&amp;gt;2-&amp;gt;1的路徑，&lt;br&gt;
其實相當於從根節點10走到1的路徑和，減去節點10。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;換句話說，如果我們每走到一個節點，都將路徑和記錄下來，&lt;br&gt;
那麼我們就可以用前面過往的路徑和，&lt;br&gt;
來表達出所有達到現在這個節點的路徑和。&lt;/p&gt;
&lt;p&gt;例如：&lt;br&gt;
1其實等於&lt;strong&gt;10 -&amp;gt; 5 -&amp;gt; 2&lt;/strong&gt; -&amp;gt; 1 去掉** 10 -&amp;gt; 5 -&amp;gt; 2&lt;br&gt;
2** -&amp;gt; 1等於** 10 -&amp;gt; 5 -&amp;gt; 2** -&amp;gt; 1去掉** 10 -&amp;gt; 5&lt;br&gt;
5 -&amp;gt; 2** -&amp;gt; 1等於** 10 -&amp;gt; 5 -&amp;gt; 2** -&amp;gt; 1去掉** 10**&lt;/p&gt;
&lt;p&gt;這樣足夠清楚了嗎XD？&lt;br&gt;
因此，我們要做的事情有：&lt;br&gt;
0. 建一個dictionary或hashmap，&lt;br&gt;
當中key/value分別代表路徑和/路徑和出現的次數。&lt;br&gt;
同時，將(0, 1)置入字典當中。(這裡稱之為preSum)&lt;br&gt;
(方便我們在剛好等於根節點到當前節點總長時計算)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;呼叫遞迴DFS函式並回傳其結果。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在DFS函式中，遍歷整棵二元樹：&lt;br&gt;
2.0. 檢查節點是否存在，不存在則回傳0&lt;br&gt;
2.1. 將當前的節點值加上根節點的値，做為現在的總和(currSum)&lt;br&gt;
2.2. 初始化res，其值為currSum-target在preSum中出現的次數&lt;br&gt;
2.3. 分別向左右節點遞迴呼叫DFS函式，將得到的結果加到res&lt;br&gt;
2.4. 由於這條路徑只能一路向下，&lt;br&gt;
所以要回到上一層前，&lt;br&gt;
需將剛剛加過的1次記錄從preSum中扣掉(backtracking)。&lt;br&gt;
2.5. 回傳res&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分preSum使用HashMap，留意先進行一次put，&lt;br&gt;
再放入helper函式中做DFS；&lt;br&gt;
helper函式中的部分，由於HashMap本身找不存在的值會出錯，&lt;br&gt;
別忘了使用getOrDefault來給定預設值(當然，你要用containsKey也行)。&lt;br&gt;
在遞迴取得左右兩邊節點的符合路徑數加總後，&lt;br&gt;
別忘記回傳前要將加上去的刪掉，才符合回溯法的要件。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/5143526b20200b9535b866e51d91a96d.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分大同小異，&lt;br&gt;
不同的是我們可以用defaultdict來將預設值當作0，&lt;br&gt;
從Python的寫法中應該可以更清晰看見回溯法的樣貌。&lt;br&gt;
(先加1後減1)&lt;br&gt;
這邊的helper直接寫成子函式，&lt;br&gt;
所以我們就不需使用self.xxx的形式來呼叫了。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/7e4a95c35aa33ed530333b6371dfcc1b.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(N*樹深)，每個節點均需要經過一次，&lt;br&gt;
每個節點最多可以成立d個preSum值，&lt;br&gt;
d為樹的深度，以平衡樹來說則是log(N))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 104 Tree (17) / DFS (14) / Backtracking (6)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-104-tree-17-dfs-14-backtracking-6/</link><pubDate>Tue, 18 Aug 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-104-tree-17-dfs-14-backtracking-6/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 104 Tree (17) / DFS (14) / Backtracking (6)" /&gt;&lt;p&gt;&lt;strong&gt;0113. Path Sum II (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;容筆者工商一下， &lt;strong&gt;「從Leetcode學演算法｜進階篇」及&lt;/strong&gt; 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p&gt;
&lt;p&gt;目前只剩下給讀者的&lt;strong&gt;進階篇+面試篇(3150)&lt;/strong&gt; 和&lt;strong&gt;全套同捆優惠(3990)&lt;/strong&gt; 了QQ&lt;br&gt;
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;br&gt;
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeall&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;內容介紹：&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;/p&gt;
&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A leaf is a node with no children.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Given the below binary tree and &lt;code&gt;sum = 22&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 8
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 11 13 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7 2 5 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Return:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [5,4,11,2],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [5,8,4,5]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;分析/解題&lt;br&gt;
給定一個二元樹以及目標的和(sum)，找出所有根節點到葉的路徑，這些路徑各自的和要等於給定的和。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;這一題是一整組Path Sum系列題的第二題。&lt;br&gt;
由於要找出路徑，所以我們需要一組記錄當前路徑current的位置的list。&lt;br&gt;
同時，要能夠判定是否要確認這條路徑OK的狀態，&lt;br&gt;
只取決於現在是否走到葉節點(因為題目要求)；&lt;br&gt;
並且走到葉節點時，左右也都沒有節點了，就無法往下走。&lt;/p&gt;
&lt;p&gt;我們可以用一個result的list記錄最終處理完的結果，&lt;br&gt;
接著使用&lt;strong&gt;DFS&lt;/strong&gt; 的方式往下找。&lt;/p&gt;
&lt;p&gt;那麼自然我們每走過一個節點，&lt;br&gt;
就要將sum減去現在root的値，同時記錄到current上。&lt;/p&gt;
&lt;p&gt;接下來要往下走還是檢查呢？&lt;br&gt;
當然就是看左右節點是否為NIL且sum和root的値是否相等啦！&lt;br&gt;
如果是的話，可以將result加上走到現在的路徑；&lt;br&gt;
如果不是的話，則以DFS往左和往右走(不要忘記去檢查NIL的狀況)。&lt;br&gt;
這整段走完要回到上一層的時候，表示已經處理完了，&lt;br&gt;
&lt;strong&gt;不要忘記我們先前將這層root的値放進了current裡面，&lt;br&gt;
所以我們應該要將其移除。&lt;/strong&gt;(** Backtracking**的部分)&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分我們可以使用同名但不同參數長度的函式，&lt;br&gt;
直接利用開頭檢查root，&lt;br&gt;
來順便處理後續帶入root.left/root.right所需要的檢查。&lt;br&gt;
Backtracking的部分，&lt;br&gt;
currentResult先加上root.val後，後續再進行remove即可；&lt;br&gt;
而留意由於我們不斷地在變換currentResult，&lt;br&gt;
不要忘記要將其複製一份以加到result裡面，而非直接用加的。&lt;br&gt;
(使用&lt;strong&gt;new LinkedList(currentResult)&lt;/strong&gt; )&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/6d08f8daf783bd267da27465c43c98fe.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;同理，Python的部分一樣需要複製，&lt;br&gt;
我們可以寫成curr[:]以複製一份用來讓res進行附加。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/384a6f215dc4c816f3bbdb93edbe8fb8.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(logN)，因為整棵樹要遍歷過一遍，&lt;br&gt;
然後平均而言，樹的深度會到O(logN)，&lt;br&gt;
所以空間複雜度所以空間複雜度，這個部分不包含result的占用空間)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 103 Tree (16) / DFS (13) / BFS (3) / Queue (4)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-103-tree-16-dfs-13-bfs-3-queue-4/</link><pubDate>Sat, 08 Aug 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-103-tree-16-dfs-13-bfs-3-queue-4/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 103 Tree (16) / DFS (13) / BFS (3) / Queue (4)" /&gt;&lt;p&gt;&lt;strong&gt;0112. Path Sum (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;容筆者工商一下， &lt;strong&gt;「從Leetcode學演算法｜進階篇」及&lt;/strong&gt; 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p&gt;
&lt;p&gt;目前只剩下給讀者的&lt;strong&gt;進階篇+面試篇(3150)&lt;/strong&gt; 和&lt;strong&gt;全套同捆優惠(3990)&lt;/strong&gt; 了QQ&lt;br&gt;
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;br&gt;
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeall&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;內容介紹：&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;/p&gt;
&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A leaf is a node with no children.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Given the below binary tree and &lt;code&gt;sum = 22&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 8
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 11 13 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7 2 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;return true, as there exists a root-to-leaf path &lt;code&gt;5-&amp;gt;4-&amp;gt;11-&amp;gt;2&lt;/code&gt; which sum is 22.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一棵二元樹，試決定該二元樹是否有一個從根到葉的路徑，&lt;br&gt;
使得路徑上的節點總和恰等於給定的目標和。&lt;/p&gt;
&lt;p&gt;這一題是一整組Path Sum系列題的第一題，&lt;br&gt;
除了接下來幾篇會陸續談到系列題外，這篇也想著重給讀者一個提醒：&lt;br&gt;
&lt;strong&gt;很多時候能用DFS解的題目，通常也能用BFS解&lt;/strong&gt; (反之亦然)&lt;/p&gt;
&lt;p&gt;所以當下遇到一個題目的時候，除非有限定要求，&lt;br&gt;
否則只要&lt;strong&gt;能想到的解法就是好解法&lt;/strong&gt; ，&lt;br&gt;
不要硬逼自己一定要用DFS或一定要用BFS。&lt;br&gt;
(練習的時候，當然還是可以自我挑戰兩種都想出解來就是了XD)&lt;/p&gt;
&lt;p&gt;首先我們要留意到一件事情：&lt;br&gt;
由於是從根到葉，&lt;br&gt;
所以我們只需要在走到左右均無節點時再檢查總和是否相符即可，&lt;br&gt;
千萬不要沿途檢查呀XD！&lt;/p&gt;
&lt;p&gt;再者，由於路途經過的都會算做計入的總和，&lt;br&gt;
所以我們可以沿路將往下走所需的總和減去當前經過的節點。&lt;/p&gt;
&lt;p&gt;依照這個概念，我們可以蠻直觀地寫出一個DFS的解：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先檢查&lt;strong&gt;root如果是NIL -&amp;gt; 直接回傳False&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;檢查&lt;strong&gt;root.left/root.right&lt;/strong&gt; 是不是&lt;strong&gt;都為NIL&lt;/strong&gt; -&amp;gt; 若均為NIL，&lt;br&gt;
若&lt;strong&gt;root.val等於所需和&lt;/strong&gt; 則回傳&lt;strong&gt;True&lt;/strong&gt; ，&lt;strong&gt;否則回傳False&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;將往下走的剩下的和next定為sum — root.val(剩下需要湊的和)&lt;/li&gt;
&lt;li&gt;回傳&lt;strong&gt;hasPathSum(root.left, next) || hasPathSum(root.right, next)&lt;/strong&gt; (因為只要存在一條路徑即為True，所以兩者用&lt;strong&gt;或&lt;/strong&gt; 來連接)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;由上可知，用來判定這個位置能不能成為我們要的路徑和，&lt;br&gt;
只取決於兩點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;現在這個位置是否已經是葉(leaf)&lt;/li&gt;
&lt;li&gt;現在這個位置的値是否是剩下需要的和&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以我們也可以用BFS的方式，搭配前面講過的Queue來處理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;同樣先檢查root及處理回傳&lt;/li&gt;
&lt;li&gt;將**[(root, sum - root.val)]** 放入Queue當中&lt;/li&gt;
&lt;li&gt;進行迴圈，每次從Queue中取出一組**(curr, val)** 並檢查：&lt;br&gt;
3–1. 若curr.left/curr.right&lt;strong&gt;均為NIL&lt;/strong&gt; -&amp;gt; ** 若val為0，回傳True**&lt;br&gt;
3–2. 檢查curr.left，若存在 -&amp;gt; 將**(curr.left, val - curr.left.val)放入Queue** 中&lt;br&gt;
3–3. 對curr.right做相同處理&lt;/li&gt;
&lt;li&gt;若迴圈結束仍未回傳，則&lt;strong&gt;回傳Fals&lt;/strong&gt; e(找不到適合的路徑)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依上面的方式，我們分別在Java/Python演示不同的方法：&lt;br&gt;
(讀者也可以自行嘗試完整練完單一語言的DFS/BFS的方法)&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分，使用了DFS，所以整體而言看起來很簡單，&lt;br&gt;
不過原則上有用遞迴的題目，就盡量要留意call stack的深度會不會超過。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/ef96d203f2d348e11ecc39418a6ddb46.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分則使用了BFS，搭配deque做為queue使用，&lt;br&gt;
留意當val != 0的時候記得要繼續操作，因為你可能會有其他節點符和XD，&lt;br&gt;
這點和DFS時不一樣，請特別留意不要直接在那邊回傳False呦！&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/43e22de9d28607e24276588dc0aaf675.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(log N)或O(N)(平均)，&lt;br&gt;
因為DFS的話記憶體計算call stack深度，&lt;br&gt;
BFS的話則是要用最底部的橫向長度來看；&lt;br&gt;
如果極端的狀況的話DFS也有可能到O(N)，因為樹可能不平衡)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 102 Tree (15) / DFS (12)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/</link><pubDate>Fri, 31 Jul 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 102 Tree (15) / DFS (12)" /&gt;&lt;p&gt;&lt;strong&gt;1530. Number of Good Leaf Nodes Pairs (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;期限嘛&amp;hellip;就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/advleetcode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong&gt;&lt;br&gt;
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/allleetcode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given the &lt;code&gt;root&lt;/code&gt; of a binary tree and an integer &lt;code&gt;distance&lt;/code&gt;. A pair of two different &lt;strong&gt;leaf&lt;/strong&gt; nodes of a binary tree is said to be good if the length of ** the shortest path** between them is less than or equal to &lt;code&gt;distance&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Return &lt;em&gt;the number of good leaf node pairs&lt;/em&gt; in the tree.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001.png"
width="321"
height="321"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001_hu_d2d5b2f46fe0401a.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001_hu_dd2ba4b6efd9cc66.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,2,3,null,4], distance = 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: The leaf nodes of the tree are 3 and 4 and the length of the shortest path between them is 3. This is the only good pair.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002.png"
width="441"
height="321"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002_hu_c32ae8ce3cf43f3d.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002_hu_3bf6b4923ab43368.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="137"
data-flex-basis="329px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,2,3,4,5,6,7], distance = 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: The good pairs are [4,5] and [6,7] with shortest path = 2. The pair [4,6] is not good because the length of ther shortest path between them is 4.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [7,1,4,6,null,5,3,null,null,null,null,null,2], distance = 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: The only good pair is [2,5].
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-4"&gt;Example 4
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [100], distance = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-5"&gt;Example 5
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,1,1], distance = 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;The number of nodes in the &lt;code&gt;tree&lt;/code&gt; is in the range &lt;code&gt;[1, 2^10].&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Each node’s value is between &lt;code&gt;[1, 100]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= distance &amp;lt;= 10&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;這題是2020/07/26舉辦的199th LeetCode Weekly Contest的第3題。&lt;br&gt;
給定一個二元樹的根節點root和一個整數距離distance，&lt;br&gt;
如果兩個不同的葉節點配對，其最小距離小於等於distance，&lt;br&gt;
我們就將其稱之為好(good)。&lt;br&gt;
試回傳這棵樹好的葉節點配對的總數。&lt;/p&gt;
&lt;p&gt;我們先前應該已經提到過葉節點就是指&lt;strong&gt;左右都沒有連接節點的節點&lt;/strong&gt; ，&lt;br&gt;
那麼，這題要怎麼思考呢？&lt;/p&gt;
&lt;p&gt;我們不妨先留意一下題目給定的條件：&lt;br&gt;
節點數量是1~2¹⁰，由於&lt;strong&gt;2¹⁰=1024&lt;/strong&gt; ，所以最壞的狀況，&lt;br&gt;
遞迴的數量也就1024而已，所以應該可以不會超過call stack的上限。&lt;br&gt;
接著，1≤distance≤10決定了我們在遞迴時，&lt;br&gt;
可以適度修剪我們要處理的節點。&lt;/p&gt;
&lt;p&gt;那這題該怎麼思考呢？&lt;br&gt;
由於我們在求的是最短距離，假定我們要看兩個節點x, y，&lt;br&gt;
那麼&lt;strong&gt;最短路徑肯定是從x往上走到x, y的最低共同祖先，&lt;br&gt;
再往下走到y的位置&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;如果我們知道x, y的LCA(最低共同祖先)n，&lt;br&gt;
又知道n的左子樹的所有葉節點各自的深度，&lt;br&gt;
及右子樹的所有葉節點各自的深度，&lt;br&gt;
那麼我們就可以知道以n為LCA時，正確的節點對有哪些。&lt;br&gt;
怎麼知道？就迴圈加起來就好了嘛！&lt;/p&gt;
&lt;p&gt;那我們又怎麼知道某個節點n的左右子樹的葉節點深度呢？&lt;br&gt;
我們可以先用dfs往深處走，走到出現葉節點的時候，&lt;br&gt;
將其記錄為距離1並往上傳(因為這時候左右也都沒得走了)；&lt;/p&gt;
&lt;p&gt;那在某個非葉節點的&lt;strong&gt;n&lt;/strong&gt; 時，我們應該可以從dfs的結果，&lt;br&gt;
分別獲得&lt;strong&gt;左右子樹的各個葉節點離n的距離&lt;/strong&gt; 。&lt;br&gt;
我們將兩個距離的列表分別叫作&lt;strong&gt;llt跟rlt&lt;/strong&gt; (left list, right list)，&lt;br&gt;
從llt跟rlt分別成對取出來相加，&lt;br&gt;
每發現一組葉節點距離相加&lt;strong&gt;小於等於10，全局的解就加1&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;做完檢查以後該做什麼呢？&lt;br&gt;
裡面所有的葉節點應該可以往上通用，對吧？&lt;br&gt;
可是我們左子樹和右子樹往上都導到當前的節點再往上，&lt;br&gt;
&lt;strong&gt;再往上的深度應該都要加1&lt;/strong&gt; 才對！&lt;br&gt;
所以我們應該將llt和rlt裡面的所有值都分別+1以後，&lt;br&gt;
&lt;strong&gt;放入一個新的list，這裡命名為merge，再將其往上傳。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因此，整個流程會大致如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;定一個class變數cnt，用來記錄成功配對的葉節點對的總數&lt;/li&gt;
&lt;li&gt;在主函式裡，先檢查root是否為NIL，是的話直接回傳0&lt;/li&gt;
&lt;li&gt;將root和distance帶入遞迴函式dfs中&lt;/li&gt;
&lt;li&gt;回傳cnt&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;而在dfs函式中，我們要做的事情是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;若n為NIL，回傳空的串列&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;若&lt;strong&gt;n的左右節點均為NIL&lt;/strong&gt; ，則回傳一個&lt;strong&gt;裡面只含一個1的串列&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;呼叫&lt;strong&gt;dfs(n.left, distance)&lt;/strong&gt; 及&lt;strong&gt;dfs(n.right, distance)&lt;/strong&gt; 進行遞迴，&lt;br&gt;
取得回傳的&lt;strong&gt;llt&lt;/strong&gt; 跟&lt;strong&gt;rlt&lt;/strong&gt; (記錄兩邊葉節點深度的串列)&lt;/li&gt;
&lt;li&gt;初始化一個空的串列&lt;strong&gt;merge&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;雙重迴圈，每當遇到llt和rlt的値**，&lt;br&gt;
兩兩相加會小於等於distance&lt;strong&gt;的狀況，就將&lt;/strong&gt; cnt遞增1**&lt;/li&gt;
&lt;li&gt;分別將llt和rlt的値全數+1後，&lt;strong&gt;加到merge&lt;/strong&gt; 裡&lt;br&gt;
(這邊可以檢查&lt;strong&gt;值必須小於distance&lt;/strong&gt; ，超過的話因為&lt;strong&gt;總路徑肯定超過，&lt;/strong&gt; 所以不符的不用放到merge內)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回傳merge&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;由於需要一個一個取出，並且重複使用，&lt;br&gt;
所以我們使用&lt;strong&gt;ArrayList&lt;/strong&gt; 並使用&lt;strong&gt;get&lt;/strong&gt; 來取得當中的值。&lt;br&gt;
在雙重迴圈的時候，我們可以&lt;strong&gt;順便將外層的値處理一下放到merge內&lt;/strong&gt; ，&lt;br&gt;
這樣後面就不用再重複一個新的迴圈處理。&lt;br&gt;
&lt;strong&gt;(但內層的不能這麼做，因為會被重複執行)&lt;/strong&gt;&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/0d13365f3b888363162a345bf51f0fe6.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分，cnt的累計可以使用list comprehension，&lt;br&gt;
&lt;strong&gt;處理符合的配對再來取len()&lt;/strong&gt; ，這樣寫起來會比雙重迴圈方便許多。&lt;br&gt;
llt和rlt則可以用類似的方式，最後將串列用加號組起來回傳。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/22ee498949dc5de4760ee139d546431e.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O((log N)³)/O(log N)，因為只有葉節點需要被記錄，&lt;br&gt;
空間應該跟最底層的節點數有關，而除了雙重迴圈外，&lt;br&gt;
dfs的深度也跟這棵樹的深度有關，但這個部分會受到distance的制約，&lt;br&gt;
所以實際應該比這個複雜度快不少)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 99 Tree (14) / DFS (11)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-99-tree-14-dfs-11/</link><pubDate>Mon, 13 Jul 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-99-tree-14-dfs-11/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 99 Tree (14) / DFS (11)" /&gt;&lt;p&gt;&lt;strong&gt;0404. Sum of Left Leaves (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/advleetcode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong&gt;&lt;br&gt;
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/allleetcode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Find the sum of all left leaves in a given binary tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 15 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，試求所有左葉子的總和。&lt;/p&gt;
&lt;p&gt;我們很久以前有提過二元樹的定義，&lt;br&gt;
忘記的話，請再複習一下XD&lt;br&gt;
&lt;strong&gt;而葉子的定義，就是它左右都沒有連接節點(NIL)！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;這時候，你可能會說：&lt;br&gt;
我知道，那我只要一直往左邊看就好啦！&lt;/p&gt;
&lt;p&gt;呃&amp;hellip;&amp;hellip;同學，你忘記了你的&lt;strong&gt;右子樹也可能產生左葉子&lt;/strong&gt; 嗎XD？&lt;br&gt;
範例中的15，不就是先從3的右節點20，&lt;br&gt;
再往左節點來到15所得到的嗎？&lt;/p&gt;
&lt;p&gt;那怎麼辦呢？&lt;br&gt;
所以我們在檢查所在節點是不是葉子的時候，&lt;br&gt;
還需要看看這個節點是不是&lt;strong&gt;從它的根節點往左邊走下來&lt;/strong&gt; 的。&lt;br&gt;
因此，我們可以每次分支往左右走，給出一個參數from，&lt;br&gt;
分別&lt;strong&gt;給往左子樹走的函式1，給右子樹走的函式-1&lt;/strong&gt; ，&lt;br&gt;
用來代表下一層的時候拿來判定是不是左葉子的前置依據。&lt;/p&gt;
&lt;p&gt;當我們看到from == 1且左右節點均為NIL時，&lt;br&gt;
就可以將當前的節點值回傳，&lt;br&gt;
否則的話，就繼續遞迴往下找底下子樹當中左葉的和。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分，每次先檢查root是否為null，&lt;br&gt;
接著我們的答案就用&lt;br&gt;
&lt;strong&gt;sumOfLeftLeaves(root.left, 1) + sumOfLeftLeaves(root.right, -1)&lt;/strong&gt;&lt;br&gt;
來取得。&lt;br&gt;
其他的寫法概念如前所述。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/b8babe98eabb5f320c2d4952787a4a89.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分寫一個子函式，因為這邊沒有用self，&lt;br&gt;
所以可以不用self.getSum來算。&lt;br&gt;
(也可以把add設定預設値-1，&lt;br&gt;
使用單個sumOfLeftLeaves來解此題，&lt;br&gt;
這個化簡方式很簡單，就留給讀者來練習看看XD)&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/24d3e49c96c5c0928d166dd35c6fbcaa.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，因為要經過每個節點，&lt;br&gt;
而如果考慮call stack的話，&lt;br&gt;
空間複雜度會是O(depth of Tree))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-51-bst-4-94cd8fe956ac" target="_blank" rel="noopener"
&gt;0235. Lowest Common Ancestor of a Binary Search Tree (Easy)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 98 Tree (13) / DFS (10)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-98-tree-13-dfs-10/</link><pubDate>Sat, 27 Jun 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-98-tree-13-dfs-10/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 98 Tree (13) / DFS (10)" /&gt;&lt;p&gt;&lt;strong&gt;0129. Sum Root to Leaf Numbers (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/advleetcode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong&gt;&lt;br&gt;
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
&gt;https://bit.ly/allleetcode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree containing digits from &lt;code&gt;0-9&lt;/code&gt; only, each root-to-leaf path could represent a number.&lt;/p&gt;
&lt;p&gt;An example is the root-to-leaf path &lt;code&gt;1-&amp;gt;2-&amp;gt;3&lt;/code&gt; which represents the number &lt;code&gt;123&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Find the total sum of all root-to-leaf numbers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A leaf is a node with no children.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 25
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The root-to-leaf path 1-&amp;gt;2 represents the number 12.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The root-to-leaf path 1-&amp;gt;3 represents the number 13.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Therefore, sum = 12 + 13 = 25.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [4,9,0,5,1]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1026
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The root-to-leaf path 4-&amp;gt;9-&amp;gt;5 represents the number 495.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The root-to-leaf path 4-&amp;gt;9-&amp;gt;1 represents the number 491.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The root-to-leaf path 4-&amp;gt;0 represents the number 40.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Therefore, sum = 495 + 491 + 40 = 1026.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，當中只有數字0~9，&lt;br&gt;
每個根到葉子的路徑可以表達一個數。&lt;br&gt;
舉例來說，1-&amp;gt;2-&amp;gt;3可以表達123。&lt;br&gt;
找出所有的根到葉的數字的總和。&lt;br&gt;
(葉的定義是沒有子節點的節點)&lt;/p&gt;
&lt;p&gt;這題雖然標註為Medium，但其實並不那麼難思考，&lt;br&gt;
只是定義要弄清楚而已。&lt;/p&gt;
&lt;p&gt;首先，假設我們在某個節點n，它如果左節點和右節點都沒有的話，&lt;br&gt;
意味著它是葉(leaf)，這時數字就要計入總和；&lt;br&gt;
如果有其中一個成立的話，我們應該要往下走，&lt;br&gt;
並記錄之前經過的節點値，這樣子在遇到葉的時候才能夠結算。&lt;/p&gt;
&lt;p&gt;那麼自然，由於每棵樹只有0~9，&lt;br&gt;
所以從一層樹到下一層的時候，原先經過的數字的作用會放大10倍。&lt;br&gt;
也就是說，從上一層下來的時候，如果所在是葉的話，&lt;br&gt;
我們應該要把這個數字&lt;strong&gt;乘以10以後，加上現在的節點値&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;因此，我們只要遍歷完整棵樹，&lt;strong&gt;將葉子加總&lt;/strong&gt; 起來即可。&lt;br&gt;
寫成流程應該如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;檢查根節點是否為NIL，如果是，直接回傳0(此路不通)&lt;/li&gt;
&lt;li&gt;計算上面下來的值(last)到當前根節點的值(now)的結果，&lt;br&gt;
&lt;strong&gt;now = last * 10 + root.val&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;如果左右節點均為NIL，直接回傳&lt;strong&gt;now&lt;/strong&gt; 即可(當前節點為葉)&lt;/li&gt;
&lt;li&gt;將&lt;strong&gt;root.left, now及root.right, now&lt;/strong&gt; 分別傳入做遞迴計算&lt;strong&gt;左右子樹的和&lt;/strong&gt; ，&lt;br&gt;
最後&lt;strong&gt;加總起來並回傳&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;所以我們會先沿著最左邊一路到最底，然後依序將所有節點走過，&lt;br&gt;
這樣子是先往深處走，所以是所謂的深度優先搜尋(DFS)的方法。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;另外一方面，留意由於我們最開始已經檢查了root是否為NIL，&lt;br&gt;
所以在傳入左右子節點時，可以讓前面這條檢查來確認NIL的狀況，&lt;br&gt;
也就不用再先檢查節點是否為空了。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java可以使用相同的函式名稱，&lt;strong&gt;傳入不同長度的參數&lt;/strong&gt; 來處理。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/956fb2f701ae5495dea4e301a4b5fcd0.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分，我們直接&lt;strong&gt;設定預設值&lt;/strong&gt; ，這樣就可以通用了XD&lt;br&gt;
當從根節點開始時，由於只傳入root, 自然last會是0。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/bebba246f6dd601d4698ad348c08153c.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1), 如果算上call stack的部分的話，&lt;br&gt;
平均空間複雜度是O(logN) (DFS的深度))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 93 Tree (12) / DFS (9)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-93-tree-12-dfs-9/</link><pubDate>Sun, 10 May 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-93-tree-12-dfs-9/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 93 Tree (12) / DFS (9)" /&gt;&lt;p&gt;&lt;strong&gt;0687. Longest Univalue Path (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.&lt;/p&gt;
&lt;p&gt;The length of the path between two nodes is represented by the number of edges between them.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 1 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; 2&lt;/p&gt;
&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 4 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; 2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The given binary tree has not more than 10000 nodes. The height of the tree is not more than 1000.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，尋找其最長的路徑長，&lt;br&gt;
當中的所有節點必須擁有相同的值。&lt;br&gt;
這條路徑通過或沒有通過根節點均可。&lt;br&gt;
(路徑長度的定義為兩個節點之間經過的邊(edge)的數量)&lt;/p&gt;
&lt;p&gt;由於很早我們就介紹過樹的基本性質了，&lt;br&gt;
(印象模糊的讀者請回頭參照&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-13-tree-1-52cfbdde02b2" target="_blank" rel="noopener"
&gt;0100. Same Tree&lt;/a&gt;)，&lt;br&gt;
在此就不再贅述。這題嘗試要找相同值的路徑，&lt;br&gt;
但又不限定要通過root，該怎麼思考呢？&lt;br&gt;
我們可以先考慮怎樣可以算&lt;strong&gt;一條相同值的路徑&lt;/strong&gt; 。&lt;br&gt;
一條相同值的路徑有可能有以下兩種狀況：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;從一個頂點下來，&lt;br&gt;
每次選擇往左節點走或往右節點走，到一個位置停下。&lt;br&gt;
例如：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 1 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;當中的5-5-5就是一條相同值的路徑。&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;從一個頂點進行分岔，左右各自走到一個位置停下。&lt;br&gt;
例如：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;　　　4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 4 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;當中的&lt;strong&gt;粗斜體的4-4-4&lt;/strong&gt; 就是一條從頂點往左右分岔所得到的路徑，&lt;br&gt;
可以選擇從&lt;strong&gt;左下的4 -&amp;gt; 中間的4 -&amp;gt; 再到右邊的4&lt;/strong&gt; ，這樣連成一個路徑。&lt;br&gt;
但從這邊來看可以發現，這條路徑就無法把root的4算在內，&lt;br&gt;
&lt;strong&gt;因為不管怎麼連，我們都沒辦法一筆不重複將這4個4走完。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因此，我們可以得知：&lt;br&gt;
對於某個節點來說，有經過它所能得到的最長路徑，&lt;br&gt;
有可能是從&lt;strong&gt;它的上面連下來(分岔點在它的上面&lt;/strong&gt; )，&lt;br&gt;
也可能是&lt;strong&gt;以它自己為分岔點&lt;/strong&gt; ，左右各自找完和它值相同的節點路徑。&lt;br&gt;
在第一個情況來說，&lt;strong&gt;要求它的上一個節點值和它的值相同；&lt;/strong&gt;&lt;br&gt;
第二個情況來說，則要將&lt;strong&gt;左右和它的值相同的路徑長相加&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;所以我們可以定義一個count函式，&lt;br&gt;
回傳以某個節點值來說，其下的最長所能得到的相同值的路徑長，&lt;br&gt;
當中計算的時候一邊留意當下最長的路徑長並進行更新。&lt;/p&gt;
&lt;p&gt;我們將整個題目的答案(相同值的最長路徑長)叫做mx(叫result也可以)，&lt;br&gt;
&lt;strong&gt;流程順序應為：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一開始應該先&lt;strong&gt;檢查root是否為NIL&lt;/strong&gt; ，&lt;br&gt;
如是，回傳&lt;strong&gt;0&lt;/strong&gt; (因為沒有路徑)，否則呼叫count函式，&lt;br&gt;
&lt;strong&gt;檢查它所能得到的相同值的最長路徑長&lt;/strong&gt; 。&lt;br&gt;
(傳入root節點，及當下的&lt;strong&gt;路徑節點值root.val&lt;/strong&gt; )&lt;/li&gt;
&lt;li&gt;在count當中，&lt;br&gt;
同樣應先檢查傳入的節點值是否為null，&lt;br&gt;
接下來為了要知道左右路徑的相同值的最長路徑長，&lt;br&gt;
應該要分別帶入其&lt;strong&gt;left/right節點及當前節點的值&lt;/strong&gt; 進去檢查，&lt;br&gt;
假設得到的結果分別為&lt;strong&gt;l/r&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;依照2的定義，l + r的值代表了一條可能的相同值路徑，&lt;br&gt;
所以要拿它和mx比較，將較長的路徑值更新。&lt;/li&gt;
&lt;li&gt;如果&lt;strong&gt;當前的節點值&lt;/strong&gt; 和**傳進來的路徑節點值兩者相同，&lt;br&gt;
代表有機會可以考慮上面提到過的&lt;br&gt;
「&lt;strong&gt;從一個頂點下來，每次選擇往左節點走或往右節點走，&lt;br&gt;
到一個位置停下。&lt;/strong&gt;」的狀況，&lt;br&gt;
這時候要回傳的值會是左右路徑長較長的部分+1。&lt;br&gt;
(因為要包含左節點/右節點到當前節點的這個路徑)&lt;/li&gt;
&lt;li&gt;上面的判斷不成立的話，代表路徑從上面下來到這邊斷掉了。&lt;br&gt;
(值不相同)，這時候應該回傳0，代表相同值路徑到這邊沒辦法繼續。**&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上面的流程順序，請讀者務必自行畫圖推導，&lt;br&gt;
會比較清楚整個思考過程。&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分mx直接宣告一個class變數即可，其它就是使用Math.max，&lt;br&gt;
及檢查null的部分，並不複雜。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/08af5452682a0112c7484b118310a12e.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的話，可以使用self.mx來宣告，&lt;br&gt;
並且在__init__時進行處理，&lt;br&gt;
其它就是一樣注意呼叫時不要忘記用&lt;strong&gt;self&lt;/strong&gt; 即可。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/2de59e38d37647b769952cc56f3fa375.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，如果空間要算上call stack的部分的話，&lt;br&gt;
則是O(TreeNode的高度)。)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p&gt;
&lt;p&gt;筆者開設的系列同名線上課程：&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong&gt; 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br&gt;
並實際完整練習&lt;strong&gt;20題&lt;/strong&gt; 精選考古題，&lt;br&gt;
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br&gt;
&lt;strong&gt;Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong&gt; &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
&gt;** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 84 Tree (11) / DFS (8)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/</link><pubDate>Fri, 24 Jan 2020 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 84 Tree (11) / DFS (8)" /&gt;&lt;p&gt;&lt;strong&gt;0116. Populating Next Right Pointers in Each Node (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;You are given a &lt;strong&gt;perfect binary tree&lt;/strong&gt; where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct Node {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; int val;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Node *left;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Node *right;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Node *next;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Initially, all next pointers are set to &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You may only use constant extra space.&lt;/li&gt;
&lt;li&gt;Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001.png"
width="800"
height="273"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001_hu_3023d38a6e81834b.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001_hu_5cbd9b16c7852a62.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="293"
data-flex-basis="703px"
&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: root = [1,2,3,4,5,6,7]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,#,2,3,#,4,5,6,7,#]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with &amp;#39;#&amp;#39; signifying the end of each level.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個完美二元樹(perfect binary tree)，&lt;br&gt;
也就是所有葉子都在相同level且所有父節點均有兩個子節點。&lt;br&gt;
在Node的定義中增加一個next的定義，&lt;br&gt;
如圖所示，每個節點的next為其右邊的節點，&lt;br&gt;
如右邊已無節點，則為NULL。&lt;br&gt;
(最開始的時候預設所有節點的next均為NULL)&lt;br&gt;
請把整個next的定義完成。&lt;/p&gt;
&lt;p&gt;由於這個題目已經有提到說只能用常數的額外記憶體空間了，&lt;br&gt;
但同時將遞迴導致的stack(也就是call stack)當作不算，&lt;br&gt;
所以使用簡單的遞迴可以簡單達到目的。&lt;/p&gt;
&lt;p&gt;最直觀的方式，就是先檢查root是否是null，&lt;br&gt;
接下來呼叫一個helper function，代入左節點和右節點來處理，&lt;br&gt;
只要左節點不是NULL，則將左節點的next設為右節點；&lt;br&gt;
接下來則要分別處理這三個連接：&lt;br&gt;
&lt;strong&gt;1. 左節點的left -&amp;gt; 左節點的right&lt;br&gt;
2. 左節點的right -&amp;gt; 右節點的left&lt;br&gt;
3. 右節點的left -&amp;gt; 右節點的right&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;當然，也可以從root為中心出發，&lt;br&gt;
這時候每次要關注的應該是root.left -&amp;gt; root.right，&lt;br&gt;
及root.right -&amp;gt; root.next.left。&lt;/p&gt;
&lt;p&gt;如果想要用迭代的方式呢？&lt;br&gt;
我們留意到每次開始進行連接的都是當個階層的最左邊的節點，&lt;br&gt;
從&lt;strong&gt;Figure B&lt;/strong&gt; 上來看的話，即為1, 2, 4…等節點。&lt;br&gt;
所以我們最開始應該要從一個階層的最左邊的節點&lt;br&gt;
(這邊叫做level_first)開始進行迭代，將當前的節點稱為curr&lt;br&gt;
分別將&lt;strong&gt;curr.left -&amp;gt; curr.right&lt;/strong&gt; 及&lt;strong&gt;curr.right -&amp;gt; curr.next.left。&lt;br&gt;
接著讓curr遞移到curr.next。&lt;br&gt;
所以每次連接兩組next的關係，直到curr走到NULL為止。&lt;br&gt;
這時候這層走完以後，進行到下一層，&lt;br&gt;
level_first應該遞移到level_first.left。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;依此，寫成如下的程式碼。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;在Java中，上述三種方法均有列出，&lt;br&gt;
順序剛好跟上面提到的相反，&lt;br&gt;
請務必留意在接續前必須要留意要確定節點是否為null的狀況。&lt;br&gt;
如果計入call stack的話，只有迭代的方式是O(1)才對。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/889bec573f69f5640c33455484b98209.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分大同小異，不要忘記使用self來呼叫，&lt;br&gt;
這邊僅列出第二種和第三種。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/58b0d724cf6dc9a63281d6eb428989b2.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，如果不考慮Call Stack的話。&lt;br&gt;
如果考慮的話上面只有直接使用迴圈迭代的是O(1))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p&gt;
&lt;p&gt;筆者開設的系列同名線上課程：&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong&gt; 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br&gt;
並實際完整練習&lt;strong&gt;20題&lt;/strong&gt; 精選考古題，&lt;br&gt;
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br&gt;
&lt;strong&gt;Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong&gt; &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
&gt;** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 62 Tree (10)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-62-tree-10/</link><pubDate>Wed, 16 Oct 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-62-tree-10/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 62 Tree (10)" /&gt;&lt;p&gt;&lt;strong&gt;0102. Binary Tree Level Order Traversal (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, return the &lt;em&gt;level order&lt;/em&gt; traversal of its nodes’ values. (ie, from left to right, level by level).&lt;/p&gt;
&lt;p&gt;For example:&lt;br&gt;
Given binary tree &lt;code&gt;[3,9,20,null,null,15,7]&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 15 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;return its level order traversal as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [3],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [9,20],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [15,7]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，回傳其節點値的層序遍歷結果。&lt;/p&gt;
&lt;p&gt;我們在&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-43-bfs-1-queue-2-d0bbff83f5c1?source=friends_link&amp;amp;sk=0db81ed4dcf2f7e4b93c7935b3f24a3a" target="_blank" rel="noopener"
&gt;先前的文章&lt;/a&gt;中，&lt;br&gt;
已經提到過層序走訪(level-order traversal)的概念了，&lt;br&gt;
按照題目範例，這邊要將level分層開來。&lt;/p&gt;
&lt;p&gt;對於&lt;strong&gt;遞迴&lt;/strong&gt; 解來說，如果使用一般的DFS的話，&lt;br&gt;
我們將不知道哪一個節點位在哪一個level上，&lt;br&gt;
故我們將必須&lt;strong&gt;加入變數level&lt;/strong&gt; ，&lt;br&gt;
讓level的值來幫助我們辨別要加到List的哪個level區塊中。&lt;/p&gt;
&lt;p&gt;所以對於遞迴解而言，在&lt;strong&gt;主函式&lt;/strong&gt; 中：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;檢查根節點&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;將root的值加入&lt;strong&gt;第0層的list&lt;/strong&gt; 中，再將該list加到答案&lt;strong&gt;res&lt;/strong&gt; 中&lt;/li&gt;
&lt;li&gt;呼叫幫助用的函式，&lt;strong&gt;將level遞増代入&lt;/strong&gt; (表下一層)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在&lt;strong&gt;幫助用函式&lt;/strong&gt; 中：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先檢查代入進來的節點，&lt;br&gt;
若&lt;strong&gt;遇到NIL則表示到此為止&lt;/strong&gt; ，進行回傳即可。&lt;/li&gt;
&lt;li&gt;檢查目前&lt;strong&gt;res的size&lt;/strong&gt; 和&lt;strong&gt;level&lt;/strong&gt; 的關係，&lt;br&gt;
若相等則表示要開一個新的list(因為&lt;strong&gt;level從0起算&lt;/strong&gt; )；&lt;br&gt;
否則，找到對應level的list，將該節點的值加入。&lt;/li&gt;
&lt;li&gt;分別檢查左節點和右節點&lt;strong&gt;進行遞迴&lt;/strong&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;觀察這樣子的遍歷方式，讀者應該可以發現一點：&lt;br&gt;
&lt;strong&gt;幫助用的函式本質上就是在做pre-order traversal。&lt;/strong&gt; 之所以會達成我們想要的效果，是因為我們額外記錄了level這個資訊。&lt;/p&gt;
&lt;p&gt;如果使用&lt;strong&gt;迭代法&lt;/strong&gt; 來解呢？&lt;br&gt;
我們可以建立一個&lt;strong&gt;Queue&lt;/strong&gt; ，在每一層&lt;strong&gt;先行取得Queue的大小(長度)&lt;/strong&gt; ，&lt;br&gt;
每次迴圈只要剛好執行這個次數，&lt;br&gt;
就可以不斷&lt;strong&gt;利用相同的Queue來堆出不同的層數&lt;/strong&gt; ，&lt;br&gt;
再分頭&lt;strong&gt;將對應的左節點和右節點推入Queue中&lt;/strong&gt; 。&lt;br&gt;
(記得要先檢查，非NIL才需要推入)&lt;br&gt;
&lt;strong&gt;最終所有節點都遍歷過一遍時，&lt;br&gt;
剛好Queue裡面也不會留存任何節點。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;依照上述說明，請參考對應的程式碼。&lt;/p&gt;
&lt;p&gt;Java的部分，記得用來檢查的&lt;strong&gt;isEmpty()&lt;/strong&gt; ，以及可以用&lt;strong&gt;LinkedList&lt;/strong&gt; 來實作&lt;strong&gt;Queue&lt;/strong&gt; 的部分。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/bef29b911d5d5fc9adf83bcc6baf5bf5.js"&gt;&lt;/script&gt;
&lt;p&gt;Python用&lt;strong&gt;deque&lt;/strong&gt; (記得我們提到過的，&lt;strong&gt;list在移除左端的部分效率較差&lt;/strong&gt; )&lt;br&gt;
另外，若幫助函式沒有要再被其他函式使用，&lt;br&gt;
是可以考慮如底下34行以後這樣子寫成子函式的方式再呼叫的，&lt;br&gt;
可以省去要加一堆self的狀況。&lt;br&gt;
(但要記得：Python函式要&lt;strong&gt;先宣告才能呼叫&lt;/strong&gt; )&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/16ecc6189b7f5f63b5733d2f5f9fb600.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(N)，因為要遍歷全部節點並記錄)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 50 Tree (9)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-50-tree-9/</link><pubDate>Sun, 15 Sep 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-50-tree-9/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 50 Tree (9)" /&gt;&lt;p&gt;&lt;strong&gt;0226. Invert Binary Tree (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Invert a binary tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Input:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1 3 6 9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 7 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;9 6 3 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Trivia:&lt;/strong&gt;&lt;br&gt;
This problem was inspired by &lt;a class="link" href="https://twitter.com/mxcl/status/608682016205344768" target="_blank" rel="noopener"
&gt;this original tweet&lt;/a&gt; by &lt;a class="link" href="https://twitter.com/mxcl" target="_blank" rel="noopener"
&gt;Max Howell&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目要求反轉一個二元樹。&lt;/p&gt;
&lt;p&gt;我們今天來看一題經典的題目，&lt;br&gt;
這題經典的原因也許不是在於它有多困難，&lt;br&gt;
而是在於這問題背後的故事XD&lt;/p&gt;
&lt;p&gt;或許另一方面也可以看看他本人在Quora上的&lt;a class="link" href="https://www.quora.com/Whats-the-logic-behind-Google-rejecting-Max-Howell-the-author-of-Homebrew-for-not-being-able-to-invert-a-binary-tree" target="_blank" rel="noopener"
&gt;回應&lt;/a&gt;。&lt;br&gt;
所以演算法很重要有沒有XDD&lt;br&gt;
(據稱有一種說法是說當時的題目是要求min-max的反轉，這邊暫不討論，&lt;br&gt;
我們以左右反轉為準)&lt;/p&gt;
&lt;p&gt;相信大家經過前面的一堆二元樹相關題目以後，&lt;br&gt;
應該已經對二元樹駕輕就熟了，應該可以輕鬆地寫出遞迴方式的版本。&lt;/p&gt;
&lt;p&gt;跟之前的Symmetric Tree相似，&lt;br&gt;
只是這次我們直接將一棵樹的左右節點交換，&lt;br&gt;
除了交換以外，它們的左右子樹的部分也要再度進行交換。&lt;/p&gt;
&lt;p&gt;所以我們會拆成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;檢查root是不是null (是的話代表這條路到底了，直接回傳null)&lt;/li&gt;
&lt;li&gt;將root.left和root.right進行交換&lt;/li&gt;
&lt;li&gt;將root.left和root.right分別做為參數，呼叫函式進行遞迴&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/c206e5d6332ba13462b890d8cf21c256.js"&gt;&lt;/script&gt;
&lt;p&gt;Python寫得再簡單一點，不過意思是一樣的XD&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/c206e5d6332ba13462b890d8cf21c256.js"&gt;&lt;/script&gt;
&lt;p&gt;你以為這樣就結束了嗎？&lt;br&gt;
我們將繼續來探討一下如果是迭代解的話該怎麼處理。&lt;/p&gt;
&lt;p&gt;如果思考一下前面的遞迴解，&lt;br&gt;
會發現一件事情：&lt;br&gt;
&lt;strong&gt;對於一個我們造訪的節點而言，&lt;br&gt;
我們所影響到的只有其左節點和右節點，&lt;/strong&gt;&lt;br&gt;
當下這個節點的値並不會受任何影響。&lt;br&gt;
所以我們只需要保證當走到這個節點的時候，&lt;br&gt;
&lt;strong&gt;關於這個節點以上的操作已經做完&lt;/strong&gt; 即可，&lt;br&gt;
那麼要保證這點的話，只要使用&lt;strong&gt;level order&lt;/strong&gt; 的方式，&lt;br&gt;
我們按順序操作即可做完所有反轉的動作。&lt;/p&gt;
&lt;p&gt;由於是先將同一層的做完才會進到下一層，&lt;br&gt;
也可以視作是BFS的方式。&lt;br&gt;
按順序作的話，&lt;br&gt;
可以使用Queue來處理這樣子的問題，步驟大致上是：&lt;br&gt;
0. 檢查root是否為NIL，是的話直接回傳NIL&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;建立一個queue(python請用&lt;strong&gt;deque&lt;/strong&gt; )&lt;/li&gt;
&lt;li&gt;將root放入queue中&lt;/li&gt;
&lt;li&gt;每次從queue中取出一個節點，將其&lt;strong&gt;左右位置互換&lt;/strong&gt; ，&lt;br&gt;
並分別將&lt;strong&gt;左右節點中非NIL的節點放入queue中&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;重複3直到queue中沒有節點&lt;/li&gt;
&lt;li&gt;回傳root&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Java:&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/ed93a54c714a8242e4df6a93f8986b2a.js"&gt;&lt;/script&gt;
&lt;p&gt;Python:&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/78234534e829f23362fc44e4b2b5c32f.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(因每個節點均要和另一個位置進行對調，所以時間複雜度為O(N)。&lt;br&gt;
空間複雜度會受到樹的平衡程度影響。&lt;br&gt;
&lt;strong&gt;平衡狀態&lt;/strong&gt; 的話空間複雜度對遞迴解來說是&lt;strong&gt;O(logN)(call stack)&lt;/strong&gt; ，&lt;br&gt;
而對迭代解來說是&lt;strong&gt;O(N)&lt;/strong&gt; (因為最大是最底部那層)&lt;br&gt;
(這時候反而越不平衡每層的節點會越不容易太多))&lt;/p&gt;
&lt;p&gt;「這兩種解哪種是DFS？哪種是BFS？」&lt;br&gt;
(遞迴解是DFS(一路走到最深才回頭)，迭代解是BFS(當層走完才往下層走))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 42 Backtracking (1) / Tree (8)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/</link><pubDate>Thu, 29 Aug 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 42 Backtracking (1) / Tree (8)" /&gt;&lt;p&gt;&lt;strong&gt;0257. Binary Tree Paths (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, return all root-to-leaf paths.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A leaf is a node with no children.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [&amp;#34;1-&amp;gt;2-&amp;gt;5&amp;#34;, &amp;#34;1-&amp;gt;3&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Explanation: All root-to-leaf paths are: 1-&amp;gt;2-&amp;gt;5, 1-&amp;gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，回傳其所有根到葉的路徑。&lt;br&gt;
這題是Easy難度的題目，剛好藉由它來講一下&lt;strong&gt;回溯法(Backtracking)&lt;/strong&gt; 。&lt;br&gt;
這個題目看起來挺簡單的，如果沒有特別要求的話，寫起來也不難，&lt;br&gt;
依照遞回的模式就可以順利解決，&lt;br&gt;
思路大致上是&lt;strong&gt;每走一步就將root的值串上path字串&lt;/strong&gt; ，&lt;br&gt;
直到左右均無節點，表示已走到葉節點了，即可將其放到結果res中。&lt;/p&gt;
&lt;p&gt;所以一般可能會寫成這樣：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001.png"
width="554"
height="323"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001_hu_81768293eb260095.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001_hu_311c8f185488e9e3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="171"
data-flex-basis="411px"
&gt;&lt;/p&gt;
&lt;p&gt;可以通過但不盡理想的遞回解&lt;/p&gt;
&lt;p&gt;這麼做其實不盡理想，&lt;br&gt;
因為我們會發現裡面的&lt;strong&gt;每一個tmp其實都是使用一個新的變數&lt;/strong&gt; ，&lt;br&gt;
顯然這件事情會讓我們花費更多的空間(因為產生新的變數)。&lt;br&gt;
怎麼辦呢？這時候就到了回溯法上場的時候了。&lt;/p&gt;
&lt;p&gt;我們之前有介紹過&lt;strong&gt;DFS/BFS&lt;/strong&gt; ，&lt;br&gt;
分別代表著&lt;strong&gt;深度優先搜尋&lt;/strong&gt; 和&lt;strong&gt;廣度優先搜尋&lt;/strong&gt; ，&lt;br&gt;
如這題前面的解法其實也可以當作DFS來看待，&lt;/p&gt;
&lt;p&gt;而&lt;strong&gt;回溯法的概念又更廣泛一些&lt;/strong&gt; ：&lt;br&gt;
在每個階段將&lt;strong&gt;所有可能性列出&lt;/strong&gt; ，&lt;br&gt;
經過檢查&lt;strong&gt;排除&lt;/strong&gt; 掉不可能的解後，&lt;strong&gt;往下一個階段&lt;/strong&gt; 進行搜尋；&lt;br&gt;
如果這個階段的&lt;strong&gt;所有分支均不成立&lt;/strong&gt; ，&lt;br&gt;
則&lt;strong&gt;回復到上一個階段&lt;/strong&gt; 的搜尋，並&lt;strong&gt;取消&lt;/strong&gt; 掉這個階段所造成的影響。&lt;br&gt;
(過程中視要求，可在找到所有答案後才回傳，或者找到第一個答案就回傳)&lt;/p&gt;
&lt;p&gt;簡單來說，就是&lt;strong&gt;一個一個試，&lt;br&gt;
走錯了就回頭&lt;/strong&gt;，而且記得先前** 試的痕跡要處理掉**就對了XD&lt;br&gt;
聽起來可能還是有點抽象，我們講這題的實作方式好了。&lt;/p&gt;
&lt;p&gt;要進行回溯法，首先要&lt;strong&gt;確立要處理的對象&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;例如這題裡面最重要的是&lt;strong&gt;節點經過的路徑&lt;/strong&gt; ，&lt;br&gt;
那麼我們應該可以將當前的路徑當作主要處理的對象：&lt;br&gt;
每次在遞迴函式中應該要做的事情有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;將當前的&lt;strong&gt;根節點&lt;/strong&gt; 加到&lt;strong&gt;路徑&lt;/strong&gt; 的ArrayList中&lt;/li&gt;
&lt;li&gt;如果&lt;strong&gt;左節點&lt;/strong&gt; 存在，遞迴進行&lt;strong&gt;左子樹&lt;/strong&gt; 的部分&lt;/li&gt;
&lt;li&gt;如果&lt;strong&gt;右節點&lt;/strong&gt; 存在，遞迴進行&lt;strong&gt;右子樹&lt;/strong&gt; 的部分&lt;/li&gt;
&lt;li&gt;如果&lt;strong&gt;左右節點均不存在&lt;/strong&gt; ，表示&lt;strong&gt;該路徑是答案要求的其中一條&lt;/strong&gt; ，&lt;br&gt;
將整個路徑內的節點值按照要求的格式&lt;strong&gt;輸出到結果res中&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;走完前4步，&lt;strong&gt;這個階段的可能性均搜索完畢&lt;/strong&gt; ，&lt;br&gt;
所以要回到上一個階段，這時&lt;strong&gt;在1.的時候加入的根節點應該要被移除&lt;/strong&gt; ，&lt;br&gt;
因為上一個階段並沒有它。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以看到在回溯法中，路徑的部分是&lt;strong&gt;所有函式共用&lt;/strong&gt; 的，&lt;br&gt;
所以只要妥善處理用完後復原，即可使用一個List來處理整個樹的狀況，&lt;br&gt;
這個List最大的占用空間就是&lt;strong&gt;這棵樹的深度&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;依此，我們可以寫出其程式碼。&lt;/p&gt;
&lt;p&gt;Java的部分，這邊用DFS來命名遞迴的函式名，&lt;br&gt;
也可以叫getPath，可依讀者喜號命名。&lt;br&gt;
使用StringBuilder來進行字串的整理(加上”-&amp;gt;”)，&lt;br&gt;
以及使用ArrayList/LinkedList來處理path相關的部分。&lt;br&gt;
(應該是用哪個都可以啦XD 題目只限定List)&lt;br&gt;
最後不要忘記每次該階段做完要將最後一個進行移除(remove)。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/2e94391aaf8a2a5f54b587813db51366.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部份我們可以直接使用List來處理，&lt;br&gt;
並且利用&lt;strong&gt;join&lt;/strong&gt; 的特性可以很方便地串接所有的path。&lt;br&gt;
最後一樣不要忘記移除當階段的痕跡(&lt;strong&gt;pop&lt;/strong&gt; )。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/f6098638545b957af09e4e7432330adc.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(時間複雜度為O(N)(因為要掃過整棵樹)；&lt;br&gt;
空間複雜度的部分，使用的path在平衡的狀態下複雜度是O(logN)&lt;br&gt;
而最後的res部分如果用個數來看的話，完美的二元樹深度是O(logN)，&lt;br&gt;
路徑數是O(N)，所以總占用空間是O(N * logN) )&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;1.&lt;a class="link" href="https://leetcode.com/problems/path-sum-ii/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0113. Path Sum II&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 30 Tree (7)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-30-tree-7/</link><pubDate>Wed, 14 Aug 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-30-tree-7/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 30 Tree (7)" /&gt;&lt;p&gt;&lt;strong&gt;0144. Binary Tree Preorder Traversal (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, return the &lt;em&gt;preorder&lt;/em&gt; traversal of its nodes’ values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,null,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt; Recursive solution is trivial, could you do it iteratively?&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目給定一個二元樹，試求其Preorder Traversal(前序走訪)。&lt;/p&gt;
&lt;p&gt;先前我們介紹過&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-17-tree-3-4ac92131e075?source=friends_link&amp;amp;sk=15ce45d175234119c54b44230e8b32f2" target="_blank" rel="noopener"
&gt;Inorder Traversal&lt;/a&gt;，對於Preorder，大家應該也會有一個心理準備，就是使用遞迴會很簡單，迭代則會不容易思考XD。&lt;br&gt;
再複習一下，所謂的Preorder指的是走訪的順序依序為&lt;strong&gt;根-&amp;gt;左-&amp;gt;右&lt;/strong&gt; ，走訪的時候遇到根的時後先輸出，接著優先往左邊走，當左邊的全走完時，&lt;br&gt;
才檢查右邊的節點，依此順序將所有節點輸出。&lt;/p&gt;
&lt;p&gt;作為遞迴的方式，我們每次將根節點的值放進res(result)中，接著再呼叫遞迴依序進行左邊節點和右邊節點的走訪即可。&lt;br&gt;
Java中使用add，Python中則用append，在前面不要忘記檢查當走到NIL(null/None)的時候要退回到上一層(直接return)。&lt;/p&gt;
&lt;p&gt;那麼，迭代的方式呢？&lt;br&gt;
由於之前我們已經提到過在Python裡面，List的append/pop可以拿來當作stack的push跟pop來使用，要用Queue的話則必須用Deque。&lt;br&gt;
所以我們這邊依舊使用stack的思路來解題。&lt;/p&gt;
&lt;p&gt;我們已經知道對於stack來說有&lt;strong&gt;LIFO(後進先出)&lt;/strong&gt; 的特性，&lt;br&gt;
利用這點，我們可以讓進入stack的順序設定為右-&amp;gt;左-&amp;gt;根，&lt;br&gt;
如此pop出來的時候順序即會符合根-&amp;gt;左-&amp;gt;右的狀態。&lt;/p&gt;
&lt;p&gt;思路如下：(前面應先檢查root是否為NIL)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;設置一個stack名為st，將root放入，再設一個記錄結果的串列res。&lt;/li&gt;
&lt;li&gt;當st裡面有節點時，&lt;strong&gt;pop出一個節點n&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;將&lt;strong&gt;n的右節點&lt;/strong&gt; push至st(如該節點不為NIL)&lt;/li&gt;
&lt;li&gt;將&lt;strong&gt;n的左節點&lt;/strong&gt; push至st(如該節點不為NIL)&lt;/li&gt;
&lt;li&gt;將&lt;strong&gt;n的值&lt;/strong&gt; 放到res中&lt;/li&gt;
&lt;li&gt;重複2~5&lt;strong&gt;直到st中沒有任何節點&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這樣一來，我們可以使用一個迴圈，令res依preorder的順序拿到節點值。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/d5573c268e29f803c7e47908a964bc61.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/4b87a227dbf05ef4cf8ae77011422571.js"&gt;&lt;/script&gt;
&lt;p&gt;這題比較困難的部分就在於迭代法的解法，&lt;br&gt;
如果讀者一時無法理解，請嘗試用紙筆列出一些狀況操作，&lt;br&gt;
會較能夠體會該方法是如何利用迴圈來達到目標的。&lt;/p&gt;
&lt;p&gt;同時，&lt;strong&gt;存入根節點的值的時間點不同&lt;/strong&gt; ，&lt;br&gt;
基本就決定了它是哪一種Traversal。&lt;/p&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N), O(N)，因為最終都需要儲存整份樹攤平的結果)&lt;/p&gt;
&lt;p&gt;「樹的形狀會影響其時間空間複雜度嗎？」&lt;br&gt;
(只會影響中間空間暫存需要的大小(因為有stack或call stack)，&lt;br&gt;
但&lt;strong&gt;複雜度不變&lt;/strong&gt; )&lt;/p&gt;
&lt;p&gt;「給定一棵二元樹，&lt;br&gt;
請依序寫出preorder/inorder/postorder/levelorder的結果」&lt;br&gt;
(簡單卻重要，請讀者務必自己畫一棵並嘗試寫一下順序，&lt;br&gt;
看看是否有搞混的地方，尤其是每次印出根節點的時機很重要。)&lt;/p&gt;
&lt;p&gt;「如果該樹是BST，且改為inorder的話，&lt;br&gt;
能否找到任二節點相差的絕對值當中的最小值？」&lt;br&gt;
(利用inorder的狀態排出來的順序會是遞增排列，每次檢查相鄰的數即可。)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://leetcode.com/problems/binary-tree-postorder-traversal" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0145. Binary Tree Postorder Traversal&lt;/strong&gt; &lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 20 Tree (6)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-20-tree-6/</link><pubDate>Sat, 27 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-20-tree-6/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 20 Tree (6)" /&gt;&lt;p&gt;&lt;strong&gt;0110. Balanced Binary Tree (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, determine if it is height-balanced.&lt;/p&gt;
&lt;p&gt;For this problem, a height-balanced binary tree is defined as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;a binary tree in which the depth of the two subtrees of&lt;/em&gt; every &lt;em&gt;node never differ by more than 1.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;Given the following tree &lt;code&gt;[3,9,20,null,null,15,7]&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 15 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Return true.&lt;/p&gt;
&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;Given the following tree &lt;code&gt;[1,2,2,3,3,null,null,4,4]&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4 4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Return false.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目給定一個二元樹，試檢查其是否為高度平衡的狀態。&lt;br&gt;
前面已經提到過很多次，若是一棵樹長得不夠平均(例如都長在同一邊)，那麼在進行一些操作的時候會相當耗時間，&lt;br&gt;
這也是為什麼我們會在意一棵樹高度是否平衡的原因。&lt;/p&gt;
&lt;p&gt;而題目給的條件其實以更常見的定義來說，會定義成如下所述。&lt;br&gt;
假如底下3點成立，一棵非空的二元樹就被稱作是平衡的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;二元樹的&lt;strong&gt;左子樹是平衡的&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;二元樹的&lt;strong&gt;右子樹是平衡的&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;二元樹的&lt;strong&gt;左右子樹高的差不大於1&lt;/strong&gt; 對於一個樹的高度(或稱作深度)，&lt;br&gt;
是指從樹的根節點走到葉節點的最大長度，所以基於這點，我們的流程應該是從根節點往下，檢查以每個節點為基準的左右子樹高的差均不大於1，該二元樹即為平衡的，反之則為不平衡。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;依此，我們會需要知道除了根以外，每個節點的深度，&lt;br&gt;
故可以簡單利用遞迴來操作：&lt;/p&gt;
&lt;p&gt;先試寫看看maxdp這個函式的虛擬碼(假設你要求root這個node的深度)：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;maxdp(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if root == NIL return 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; l = maxdp(root.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r = maxdp(root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return max(l, r) + 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;當我們要求某個節點的深度時，&lt;br&gt;
&lt;strong&gt;就相當於求其左右兩邊子樹深度的較大值+1&lt;/strong&gt; 。&lt;br&gt;
(+1是因為經過了自己這個節點)&lt;/p&gt;
&lt;p&gt;回到我們原本的問題，我們想要求左右子樹的深度差不能大於1的話，只需要在maxdp函式中增加去判斷左右深度差即可。&lt;br&gt;
我們同時可以使用一個變數res來記錄是否已經發生不平衡的情況，&lt;br&gt;
一旦發生，其實可以不用繼續往下做。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;let res = true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;maxdp(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if (root == NIL or !res) return 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; l = maxdp(root.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r = maxdp(root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if (abs(l-r) &amp;gt; 1) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res = false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return max(l, r) + 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在一開始的解答的isBalanced函式中呼叫maxdp，&lt;br&gt;
最後將res回傳即可得到答案。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/e458838d8b04d2e4ade2f3c1d13beb4e.js"&gt;&lt;/script&gt;
&lt;p&gt;Python這邊展示了一個再進一步的思路：&lt;br&gt;
如果我們已經發現不平衡的狀況，可以使用-1做為代表，因為深度只可能大於或等於0，那麼，只要每次檢查是否出現-1，就不用使用額外的res變數來儲存結果，我們只需要檢查回傳是否為-1就可以判定二元樹是不是平衡了！&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/9e60476056da953f64f4acfd5cd41be9.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(最差狀況是樹很平衡，每一層都要檢查，時間複雜度是O(N)&lt;br&gt;
自行宣告的額外空間是O(1)，但遞迴中需有Call Stack，&lt;br&gt;
最糟的狀況也是O(N)(全擠在同一邊))&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 19 Tree (5)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-19-tree-5/</link><pubDate>Thu, 25 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-19-tree-5/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 19 Tree (5)" /&gt;&lt;p&gt;&lt;strong&gt;0111. Minimum Depth of Binary Tree (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, find its minimum depth.&lt;/p&gt;
&lt;p&gt;The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A leaf is a node with no children.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Given binary tree &lt;code&gt;[3,9,20,null,null,15,7]&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 15 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;return its minimum depth = 2.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目給定一個二元樹，要求找到最小的深度，也就是從根節點到最近的葉節點的路徑長。(&lt;strong&gt;葉&lt;/strong&gt; 節點是指它底下&lt;strong&gt;沒有其他小孩&lt;/strong&gt; 了)&lt;br&gt;
上一題我們講解了一題Hard的題目，讓我們稍微喘口氣，&lt;br&gt;
來看個這個比較基本的題目吧！&lt;/p&gt;
&lt;p&gt;這題概念並不複雜，只要稍微弄明白要被遞迴的主體即可。&lt;br&gt;
對一個節點來說，我們已經知道所謂的深度就是從&lt;strong&gt;根走到這個節點的長度&lt;/strong&gt; 。&lt;br&gt;
既然我們要求最小的路徑長度，可以選擇的方式就是分別看兩邊有多深，&lt;br&gt;
最後&lt;strong&gt;選擇較小的那邊&lt;/strong&gt; ，加上1即可。(因為從根走到根的左/右節點要計算到)&lt;br&gt;
那麼，左右各自有多深同樣也要取最小的路徑，&lt;br&gt;
故一樣使用相同的方法再往下遞迴。&lt;/p&gt;
&lt;p&gt;依此嘗試寫成遞迴的虛擬碼：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;minDepth(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if root == NIL return 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; l = minDepth(root.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r = minDepth(root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l == 0 or r == 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return l + r + 1 // 等同於取非NIL那條的路徑或取1(當左右都是NIL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; else
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return min(l, r) + 1 // 左右都有時取較小的路徑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;再化成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/082c58b525465438fc4e67ad655a7350.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分使用判斷是否是None來處理，&lt;br&gt;
本質上是一樣的，讀者可依個人喜好來選用寫法。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/05b0eeb98bda057b1505fee9d39bd457.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(由於必須遍歷所有節點，時間複雜度為O(N)，空間複雜度則依照stack深度而定，最糟的狀況也是O(N)，最好的狀況則是O(logN))&lt;/p&gt;
&lt;p&gt;「可以用迭代解嗎？」&lt;br&gt;
可以，但比較難想，有興趣的讀者可以嘗試使用我們還沒有仔細講過的&lt;strong&gt;level-order traversal&lt;/strong&gt; 來解此題，大致的思路是使用Queue來&lt;strong&gt;保存相同深度的所有節點&lt;/strong&gt; ，並且用另一個Queue和level進行記錄，一旦在某次出現了&lt;strong&gt;node.left和node.right均為NIL&lt;/strong&gt; 的狀況，代表在這層就遇到&lt;strong&gt;葉子&lt;/strong&gt; ，那麼就可以&lt;strong&gt;回傳level即為解答&lt;/strong&gt; 。&lt;br&gt;
這麼做的時間複雜度和空間複雜度均和&lt;strong&gt;最小深度&lt;/strong&gt; 有關，若最小深度為D，&lt;br&gt;
時間空間複雜度均為O(2^D)，雖然看起來比較可怕，&lt;br&gt;
但其實最糟的狀況是這棵二元樹是平衡的，這時2^D-1 = N；&lt;br&gt;
而其他狀況下複雜度肯定小於O(N)。&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 18 Tree (4)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-18-tree-4/</link><pubDate>Tue, 23 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-18-tree-4/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 18 Tree (4)" /&gt;&lt;p&gt;&lt;strong&gt;0124. Binary Tree Maximum Path Sum (Hard)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a &lt;strong&gt;non-empty&lt;/strong&gt; binary tree, find the maximum path sum.&lt;/p&gt;
&lt;p&gt;For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along with the parent-child connections. The path must contain &lt;strong&gt;at least one node&lt;/strong&gt; and does not need to go through the root.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [-10,9,20,null,null,15,7]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 9 20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 15 7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 42
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目給定一個二元樹，試求其上最大的路徑和的值。&lt;br&gt;
所謂路徑，就是在二元樹上任意挑兩個節點，&lt;strong&gt;從一個節點走到另一個節點，包含它們自己，所經過的所有節點值的和。&lt;/strong&gt;&lt;br&gt;
最小的條件是兩個節點相同，這時候的路徑長等同於這個節點的值。&lt;/p&gt;
&lt;p&gt;嫌前面太簡單了嗎？別急，Hard等級的題目這不就來了嗎XD&lt;br&gt;
在講解以前，建議讀者先思考一下有沒有任何頭緒並寫下來，再接著往下面看分析，相信會有比較好的收穫。&lt;/p&gt;
&lt;p&gt;3~&lt;/p&gt;
&lt;p&gt;2~&lt;/p&gt;
&lt;p&gt;1~&lt;/p&gt;
&lt;p&gt;開始囉！&lt;/p&gt;
&lt;p&gt;如果我們多拿幾組節點來進行觀察，會發現從一個節點要走到另一個節點，要先經過它們最低的共同祖先節點(這邊指從雙方往上走第一個碰頭的位置)，再走下來才行。&lt;br&gt;
以Example 1來說，2和3的最低共同祖先是1，&lt;br&gt;
以Example 2來說，15和7的最低共同祖先是20。&lt;/p&gt;
&lt;p&gt;那麼，我們怎麼決定兩個節點的路徑長呢？&lt;br&gt;
假設我們知道AB兩個節點的話，它們一定會有一個最低的共同祖先節點，&lt;br&gt;
當中&lt;strong&gt;可能是A或B自身，也可能是其他節點&lt;/strong&gt; (如前面的範例就都是其他節點，而如果取的是-10跟15的話那最低的共同祖先節點就是-10)，&lt;br&gt;
所以&lt;strong&gt;每個節點都可以有做為節點的最低共同祖先節點的可能&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;我們姑且將最低共同祖先節點叫做中繼點好了，比較方便XD&lt;br&gt;
接著，將不含中繼點的左邊的最大路徑和叫做l，右邊的最大路徑和叫做r，對於某個中繼點(node n)而言：&lt;/p&gt;
&lt;p&gt;通過中繼點n的最大路徑和 = max(n.val, n.val + l, n.val + r, n.val + l + r)&lt;br&gt;
(因為l或r都有可能是負的，所以要把這四種都考慮在內)&lt;/p&gt;
&lt;p&gt;接著我們要考慮的是，&lt;strong&gt;如果中繼點是別的點而不是現在這個點&lt;/strong&gt; ，&lt;br&gt;
我們只是&lt;strong&gt;經過&lt;/strong&gt; 它但想知道&lt;strong&gt;包含這個點往下走最大路徑和&lt;/strong&gt; 是多少的話，&lt;br&gt;
那我們只能去考慮&lt;strong&gt;n.val/n.val+l/n.val+r&lt;/strong&gt; 這三種狀況。&lt;br&gt;
(因為n.val+l+r代表這個點是做為中繼點才會有分支)&lt;/p&gt;
&lt;p&gt;所以我們可以嘗試用遞迴的方式解題，從root開始往下走到每個節點，計算&lt;strong&gt;該節點往下走的最大路徑和&lt;/strong&gt; ，並且每經過一個節點就考慮看看這個&lt;strong&gt;節點是中繼點的狀況，一旦發現最大值比現有記錄的大，就更新成新的最大值&lt;/strong&gt; 。&lt;br&gt;
由於用來遞迴的函式是一路優先往下一層節點進入(一直到最底下才能回頭依序得到各自的l跟r)，這種優先往深的方向走的方式我們一般稱為&lt;strong&gt;深度優先搜尋&lt;/strong&gt; (DFS, Depth-First Search)。&lt;/p&gt;
&lt;p&gt;寫成虛擬碼如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;define res
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;maxPathSum(root){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res = root.val
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dfs(root)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return res
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dfs(n){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; l = (n.left != NIL) ? dfs(n.left) : 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r = (n.right != NIL) ? dfs(n.right) : 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m = n.val
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m = max(m, l + m, r + m) // 單做為經過點的最大路徑和
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res = max(res, m, l + r + n.val) // m已比過3種可能，故只需再考慮中繼點
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在這個虛擬碼當中，我們&lt;strong&gt;先考慮左右是否還有連接節點&lt;/strong&gt; ，有的話就進行dfs往下找出&lt;strong&gt;經過點&lt;/strong&gt; 的最大路徑和，沒有的話則&lt;strong&gt;補上0&lt;/strong&gt; ；接著先考慮m的部分，再利用已經比過大小的m來和作為中繼點的狀況比較，最後和當前最大路徑和相比並更新結果，完整走完所有流程即可得到回傳的答案。&lt;/p&gt;
&lt;p&gt;Java的部分，這邊使用了if來作比較，實測上和一組一組依序使用Math.max來相比並沒有明顯速度上的區別，讀者可依自己喜好使用。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/53bc92125e7553e0e24feb539bd0151e.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分，留意呼叫時加上的self.即可，&lt;br&gt;
且max可適用於多個傳入值，比起Java會再方便一點。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/10c2f20cd569a3681552a2a54d57a7a6.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(每個節點均會走過一遍，故時間複雜度為O(N)&lt;br&gt;
除了res, l, r, m以外沒有額外的空間了，自行宣告的空間複雜度為O(1)，&lt;br&gt;
但進入遞迴會用到Stack，最大應該是這棵二元樹的&lt;strong&gt;高度&lt;/strong&gt; ，&lt;br&gt;
也就是最糟的狀況下可以到O(N)，最好的狀況則是O(logN))&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 17 Tree (3)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-17-tree-3/</link><pubDate>Mon, 22 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-17-tree-3/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 17 Tree (3)" /&gt;&lt;p&gt;&lt;strong&gt;0094. Binary Tree Inorder Traversal (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, return the &lt;em&gt;inorder&lt;/em&gt; traversal of its nodes’ values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,null,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [1,3,2]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt; Recursive solution is trivial, could you do it iteratively?&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個二元樹，題目要求以inorder(中序)方式回傳其節點值。&lt;br&gt;
由於上一題的關係(讀者可以回頭參照&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-16-bst-1-41d01e6a9f7a?source=friends_link&amp;amp;sk=c542299d85bd7ffd01a08c64507c47a9" target="_blank" rel="noopener"
&gt;第16篇&lt;/a&gt;)，我們已經講解過In-order的方式了，原則上就是經過&lt;strong&gt;左邊的部分-&amp;gt;中間的部分-&amp;gt;右邊的部分&lt;/strong&gt; 的順序。&lt;br&gt;
請留意這題輸出並不一定會由小到大(因為並沒有限制是二元搜尋樹)。&lt;/p&gt;
&lt;p&gt;我們先來嘗試遞迴解法，通常較為簡單，這邊重新列出上一篇提到的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inorder(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if root == NIL return
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; inorder(root.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(root.val) // Or add/append to the list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; inorder(root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;若讀者感到不太能夠掌握這個流程的運作，可回頭參考&lt;a class="link" href="https://miro.medium.com/max/685/1*V9LkwYgbTVvGee4k7NkbOQ.gif" target="_blank" rel="noopener"
&gt;第16篇的gif動畫&lt;/a&gt;。&lt;br&gt;
總體而言，&lt;strong&gt;每次我們都會走到當前所能走到的左邊&lt;/strong&gt; ，直到左邊再也沒有node(變成&lt;strong&gt;NIL&lt;/strong&gt; )時，會&lt;strong&gt;回到上一層&lt;/strong&gt; (return)，&lt;strong&gt;印出值&lt;/strong&gt; (或將其放到list中)，接著再&lt;strong&gt;往自身的右邊找&lt;/strong&gt; ；每次同樣的模式操作完以後，我們可以保證對於每個子樹，都是先拿到其左邊的節點值(們)，再來是自身，最後才是右邊的節點值(們)，從而保證這個演算法是得以遵照目標的順序完成的。&lt;/p&gt;
&lt;p&gt;由於我們會使用一個ArrayList或List來存放inorder得到的值，所以下面是採用先宣告再將其放置到另一個遞迴用函式中處理的方式。當然，如讀者只想使用一個函式來遞迴，也可以宣告一個Solution的class變數，這樣就不需要每次傳遞了。兩者各有好處，讀者可依自己喜好決定。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/23f13807df687358e8fb6d15243d76ee.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/02ea8399fd9f59a3038d5822c4db3c4f.js"&gt;&lt;/script&gt;
&lt;p&gt;那麼，如果是要求要迭代解(iterative solution)呢？&lt;br&gt;
我們回顧一下前面的作法，遞迴的時候之所以我們能回到上一層，其實是因為我們的程式有記錄上一層的函式的執行狀態，從而在return時能返回到應該繼續的那一行執行。由於&lt;strong&gt;最後一層函式在返回時必須先被呼叫到&lt;/strong&gt; ，所以電腦在儲存時是採用&lt;strong&gt;Stack&lt;/strong&gt; 的形式(因為要後進先出)。(這個堆疊又叫做The Stack或Call stack(呼叫堆疊))&lt;/p&gt;
&lt;p&gt;因此，我們想要能夠不用遞迴解的話，&lt;br&gt;
顯然我們應該要自己使用一個Stack來處理整個流程。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在In-order的流程中，首先我們是先一路走到最左邊的node，&lt;br&gt;
中途經過的node我們應該要將其放進Stack中，這樣才能回到上一層去，&lt;br&gt;
我們將這個node暫時命名為curr(current)。&lt;/li&gt;
&lt;li&gt;curr一路向左最終一定會遇到NIL，表示這排從root一路向左邊走，&lt;br&gt;
沿途的node全數放入到Stack中了。&lt;/li&gt;
&lt;li&gt;那麼我們應該要將最後一個node從Stack中拿出來(因為後進先出，最後一個node應該是最左邊的node才對)，將其放到list當中。&lt;/li&gt;
&lt;li&gt;接著將curr設為自己右邊的node。&lt;/li&gt;
&lt;li&gt;反覆上面的流程，一直到curr和stack都空掉為止。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;寫成虛擬碼如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;create a list named res
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;create a stack named stack
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curr = root
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;while ( curr != NIL or !stack.isEmpty() ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; while (curr != NIL) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack.push(curr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curr = curr.left
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curr = stack.pop()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res.add(curr.val)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curr = curr.right
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;return res
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="java-1"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/a3d0175fce2ca6f6aaadf7543781d9f2.js"&gt;&lt;/script&gt;
&lt;h3 id="python-1"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/c969c8d64b69be7f33a15ed2e19571d5.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
（O(N), O(N)，因為要走訪過整棵樹，且list要儲存整個二元樹攤平的結果）&lt;/p&gt;
&lt;p&gt;「如果我將res放在class Solution的level有什麼優缺點？」&lt;br&gt;
(優點：&lt;br&gt;
有機會速度快一點點，且通常不用傳位址給函式，因為直接能存取到。&lt;br&gt;
缺點：&lt;br&gt;
對整個class均為可見，如果這個函式是要被反複使用的話，&lt;br&gt;
要注意初始化的問題，且也有可能被其他函式修改到。)&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 14 Tree (2) / Queue (1)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-14-tree-2-queue-1/</link><pubDate>Wed, 17 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-14-tree-2-queue-1/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 14 Tree (2) / Queue (1)" /&gt;&lt;p&gt;&lt;strong&gt;0101. Symmetric Tree (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a binary tree, check whether it is a mirror of itself &lt;br&gt;
(ie, symmetric around its center).&lt;/p&gt;
&lt;p&gt;For example, this binary tree &lt;code&gt;[1,2,2,3,4,4,3]&lt;/code&gt; is symmetric:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3 4 4 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;But the following &lt;code&gt;[1,2,2,null,3,null,3]&lt;/code&gt; is not:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Bonus points if you could solve it both recursively and iteratively.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;題目給定一個二元樹，要求檢查是否為左右對稱(Symmetric)。&lt;br&gt;
繼前一篇的樹的基本以後，今天同樣來談談另一個基本題，幫助大家熟悉以外，也介紹一個資料結構Queue，用來說明我們怎麼來解迭代解的。&lt;/p&gt;
&lt;p&gt;這邊講的左右對稱是指從根節點將左右切開來看，左邊和右邊恰巧要對稱。&lt;br&gt;
要解決這個問題並不困難，但要留意小細節。&lt;/p&gt;
&lt;p&gt;首先，如果&lt;strong&gt;給定的根是NIL(null/None)&lt;/strong&gt; =&amp;gt; &lt;br&gt;
沒有東西仍然是可以達成左右對稱，所以&lt;strong&gt;必須回傳真值&lt;/strong&gt; (true/True)。&lt;/p&gt;
&lt;p&gt;扣掉這個狀況，再來觀察上面的圖可以發現，根節點毫不影響，&lt;br&gt;
接著要比較的應該是左子樹跟右子樹是否對稱。&lt;br&gt;
和前一題不同，以&lt;code&gt;[1,2,2,3,4,4,3]&lt;/code&gt;為例，要符合對稱的條件，&lt;br&gt;
應該要符合下面三點：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;左子樹根的值=右子樹根的值&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;左子樹&lt;/strong&gt; 自己的&lt;strong&gt;左子樹&lt;/strong&gt; (以本例是最左邊的3)要和&lt;strong&gt;右子樹&lt;/strong&gt; 自己的&lt;strong&gt;右子樹&lt;/strong&gt; 對稱&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;左子樹&lt;/strong&gt; 的&lt;strong&gt;右子樹&lt;/strong&gt; 要和&lt;strong&gt;右子樹&lt;/strong&gt; 的&lt;strong&gt;左子樹&lt;/strong&gt; 對稱&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;請留意1的部分，&lt;br&gt;
如果&lt;strong&gt;兩者均為NIL&lt;/strong&gt; ，表示下面不用比(空了)且&lt;strong&gt;兩者相等&lt;/strong&gt; ，&lt;br&gt;
這時候應該&lt;strong&gt;回傳真值&lt;/strong&gt; ；而接下來再判斷&lt;strong&gt;其一為NIL&lt;/strong&gt; 的狀況，表示兩者一定不相等(&lt;strong&gt;一個有節點一個是NIL&lt;/strong&gt; )，這個技巧在上一篇同樣有使用到。&lt;br&gt;
&lt;strong&gt;上面都沒成立的話，再判斷兩者值是否相等&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;所以直觀上我們可以寫出這樣的遞迴模式：&lt;br&gt;
(註:留意我們這樣寫只是用來表達整個演算的流程，它通常並不能用來在某個語言執行，這樣的用來表達概念的代碼叫作&lt;strong&gt;虛擬碼(pseudocode)，虛擬碼通常不用嚴格按照特定規範，目的只是要先將你的流程想法釐清為主。&lt;/strong&gt; )&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;isSym(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if root == NIL return true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return isSymmetric(root.left, root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;isSymmetric(l, r) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l == NIL and r == NIL return true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l == NIL or r == NIL return false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l.val != r.val return false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return isSymmetric(l.left, r.right) and
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; isSymmetric(l.right, r.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;寫成Java如下，注意我們這邊將isSymmetric函式的前2行合併了，&lt;br&gt;
使用者也可以依自己習慣決定要不要這麼寫，速度上並不會有明顯差異。&lt;br&gt;
同時，對Java而言，我們可以定義同名的函式，只要輸入的參數(parameter)型態或數量不同，JVM就可以知道哪一條式子是呼叫哪一個函式才正確。&lt;br&gt;
這個做法稱為&lt;strong&gt;函式多載(Method Overloading)&lt;/strong&gt; 。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/9e4954ddb7cba07364e1265d80e3ae98.js"&gt;&lt;/script&gt;
&lt;p&gt;Python並不支援函式多載，所以我們可以定義不同的名字來使用。&lt;br&gt;
(註: 對於所有程式語言來說，&lt;br&gt;
代表&amp;quot;&lt;strong&gt;且&lt;/strong&gt; &amp;ldquo;的操作，只要第一個條件為&lt;strong&gt;假&lt;/strong&gt; ，後面就不會再進行判斷；&lt;br&gt;
代表&amp;rdquo;&lt;strong&gt;或&lt;/strong&gt; &amp;ldquo;的操作，只要第一個條件為&lt;strong&gt;真&lt;/strong&gt; ，後面也不會再進行判斷。&lt;br&gt;
這個特性是為了節省時間，因為&lt;strong&gt;結果已經確定了&lt;/strong&gt; 。&lt;br&gt;
讀者可以留意一下這點，&lt;br&gt;
避免將一些希望一定要被執行的函式放在判斷條件的第二個以後，&lt;br&gt;
以免發生預期要做的事情結果沒做的狀況。)&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/66937a7afdf124a04fdc95310a33faf3.js"&gt;&lt;/script&gt;
&lt;p&gt;上面是遞迴的部分，接下來我們改成嘗試來使用迭代法解看看。&lt;br&gt;
這邊首先要介紹一個資料結構Queue(隊列/佇列)。&lt;br&gt;
隊列基本上就跟現場排隊名店一樣，扣除掉一些現實中的插隊之類的糟糕狀況外，基本上是&lt;strong&gt;先排隊的可以先離開排隊序列而進場，也就是說它的特性是先進先出(FIFO)。&lt;/strong&gt; 我們將放一個東西到Queue中的操作叫作&amp;rdquo;&lt;strong&gt;Offer&lt;/strong&gt; &amp;ldquo;(提供)，會放到隊列尾端；&lt;br&gt;
從Queue裡面拿一個東西出來的操作叫作&amp;rdquo;&lt;strong&gt;Poll&lt;/strong&gt; &amp;ldquo;(獲得)，會從隊列頭拿出。&lt;/p&gt;
&lt;p&gt;這樣的特性對於解這題有什麼幫助呢？&lt;br&gt;
我們可以如下操作：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先判斷root的部分，沒有問題的話拿出其左右(l跟r)，放到Queue裡面。&lt;/li&gt;
&lt;li&gt;此時Queue裡面有東西，一次拿兩個出來(poll兩次)，判斷l跟r本身&lt;br&gt;
(如同遞迴時一樣)&lt;/li&gt;
&lt;li&gt;接下來我們應該要判斷的是&lt;strong&gt;l.left, r.right跟l.right, r.left&lt;/strong&gt; ，&lt;br&gt;
所以我們將這四個節點依序offer至Queue中。&lt;/li&gt;
&lt;li&gt;重複2~3的動作直到&lt;strong&gt;Queue空掉&lt;/strong&gt; 或當中&lt;strong&gt;判斷為假&lt;/strong&gt; 的狀況即回傳&lt;strong&gt;假&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;如果Queue空掉了才離開循環，代表結果為&lt;strong&gt;真&lt;/strong&gt; ，回傳&lt;strong&gt;真&lt;/strong&gt; 值。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這裡我們利用了Queue的特性，只要依照我們目標的順序將東西放進Queue，我們就可以一直按照正確的方式拿到2個需要被判斷的節點。&lt;br&gt;
這邊要注意一點，&lt;strong&gt;如果兩個節點均為NIL，只代表這個部分往下沒有節點了，不能直接回傳真值&lt;/strong&gt; (因為其他部分還沒比較完)，只是我們在這個位置不需要再放節點進到Queue中而已。&lt;/p&gt;
&lt;p&gt;寫成虛擬碼如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;isSymmetric(root) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; create a queue named q
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if root == NIL return true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(root.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(root.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; while q is not empty {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; l = q.poll()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r = q.poll()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l == NIL and r == NIL continue
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l == NIL or r == NIL return false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if l.val != r.val return false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(l.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(r.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(l.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.offer(r.left)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意&lt;strong&gt;continue&lt;/strong&gt; 是用來表示這輪的迴圈不再繼續，直接跳到下一輪。&lt;/p&gt;
&lt;p&gt;Java的&lt;strong&gt;LinkedList&lt;/strong&gt; 已經有實作包含Queue的資料結構了，所以我們定義一個Queue時，實際上可以使用LinkedList作為宣告的物件。&lt;/p&gt;
&lt;h3 id="java-1"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/d09cb49e5bf2cedd1d32fc656262eb6a.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分，由於list的特性和Queue不太一致，&lt;br&gt;
從&lt;strong&gt;開頭取出&lt;/strong&gt; 這點會讓用list模擬Queue的行為消耗大量的時間。&lt;br&gt;
針對這點，Python有提供一個&lt;strong&gt;deque&lt;/strong&gt; 的物件可以使用，取出請用&lt;strong&gt;popleft()&lt;/strong&gt; ，放入請用&lt;strong&gt;append()&lt;/strong&gt; 即可。除了像Java這樣子的寫法以外，我們也可以將其使用list的形式每兩個作為一個單位來操作，請參閱下面的程式碼。&lt;/p&gt;
&lt;h3 id="python-1"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/549435d4df430227c40e6f734dea4f36.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(最糟的狀況均為O(N)，因為要查完所有資料有可能要塞完全部的node&lt;br&gt;
遞迴的狀況如果該樹是平衡的話，空間複雜度可以降到O(logN))&lt;/p&gt;
&lt;p&gt;「可以將左右比較的順序調過來嗎？」&lt;br&gt;
(只要對應的節點是正確的，先比左邊還是先比右邊並無差異)&lt;/p&gt;
&lt;p&gt;「如果我不想在前面單獨判斷root的話，有可能嗎？」&lt;br&gt;
(去掉第4行，並將第一次offer的(root.left, root.right)改成(root, root)即可。)&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 13 Tree (1)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/</link><pubDate>Mon, 15 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 13 Tree (1)" /&gt;&lt;p&gt;&lt;strong&gt;0100. Same Tree (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given two binary trees, write a function to check if they are the same or not.&lt;/p&gt;
&lt;p&gt;Two binary trees are considered the same if they are structurally identical and the nodes have the same value.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: 1 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 3 2 3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1,2,3], [1,2,3]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: 1 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1,2], [1,null,2]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: 1 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; / \ / \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 1 1 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1,2,1], [1,1,2]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定兩個二元樹，試寫出一個函式來檢查二者是否相等。&lt;br&gt;
(相等的定義是指樹的結構相同，且其相同位置節點的值也相等)&lt;/p&gt;
&lt;p&gt;到了第13篇，終於來到樹的部分了，想當年大學時在演算法的課上被各種資料結構搞得眼花撩亂，當中二元樹/二元搜尋樹真的只能算小兒科XD&lt;br&gt;
(不信？有心更進階的讀者可以試試看了解一下&lt;a class="link" href="https://en.wikipedia.org/wiki/Red%e2%80%93black_tree" target="_blank" rel="noopener"
&gt;紅黑樹&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;扯遠了，我們回頭來談樹。&lt;br&gt;
在程式的領域中，樹是指資料之間以一種長得像樹的方式連結在一起的資料結構(廢話XD)，以外型而言就像&lt;strong&gt;樹狀圖&lt;/strong&gt; 或&lt;strong&gt;族譜&lt;/strong&gt; 那樣子，不過它們有一點比較特別，那就是他們的&lt;strong&gt;根通常是畫在上方&lt;/strong&gt; ，下面才是支幹。&lt;br&gt;
如下圖我們所看到的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每個圈圈我們稱之為&lt;strong&gt;節點(node)&lt;/strong&gt; 。2.最上面的節點是整棵樹的起始，所以我們就稱之為&lt;strong&gt;根(root)&lt;/strong&gt; 。3. 就如族譜一樣，上面節點是下面直接連接的父母，&lt;br&gt;
所以我們稱如&lt;strong&gt;A是B和C的父節點(parent)&lt;/strong&gt; (不要問我為什麼不叫母節點XD)，而&lt;strong&gt;B和C是A的子節點(child)，&lt;/strong&gt; 同時&lt;strong&gt;B和C是兄弟節點(siblings)&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;任何從自身追尋血脈上去可以到達的節點均為你的&lt;strong&gt;祖先(ancestor)&lt;/strong&gt; 。&lt;br&gt;
比如A是所有人的祖先，而B不是G的祖先。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-001.png"
width="731"
height="688"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-001_hu_efacdea7c8a67004.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-001_hu_60a348618402d805.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="255px"
&gt;&lt;/p&gt;
&lt;p&gt;From Wikipedia: Tree&lt;/p&gt;
&lt;p&gt;樹本身並沒有規定一個節點要連接多少個節點或總共有多少個節點，&lt;br&gt;
你可以子孫滿堂開枝散葉，也可以孑然一身孤苦伶仃，只要有一個根在，&lt;br&gt;
就可以被稱做一棵樹。&lt;/p&gt;
&lt;p&gt;不過這邊要介紹的是&lt;strong&gt;二元樹(binary tree)&lt;/strong&gt; ，就有比較明確的限制了，&lt;br&gt;
每個節點最多只能有&lt;strong&gt;2&lt;/strong&gt; 個分支。且&lt;strong&gt;左右分支是視作不同&lt;/strong&gt; 的，將它們互相交換的話，前後兩個二元樹會被視為不同的二元樹。由於只有2個分支，所以一個節點的兩個子節點又可以分別被叫做左節點和右節點(left/right node)，&lt;br&gt;
單就這兩個節點來看，都可以各自視為一個二元樹，&lt;br&gt;
同樣依照左右被稱作&lt;strong&gt;左子樹/右子樹(left/right subtree)&lt;/strong&gt; 。&lt;br&gt;
後續還有一個規範更嚴格，也更常被用到的二元樹稱為&lt;strong&gt;二元搜尋樹(Binary Search Tree, BST)&lt;/strong&gt; ，這個我們之後會專門再開一篇講解。上面這些均為樹的相當基本的部分，並不困難，還請詳加閱讀後再往下。&lt;/p&gt;
&lt;p&gt;如同先前提過的linked list一樣，當一個節點它有一邊沒有連接，或者是已經沒有子節點的時候，嚴謹的資料結構會將其連接至&lt;strong&gt;NIL&lt;/strong&gt; (表示什麼都沒有)，而在&lt;strong&gt;Java中用null，Python則用None&lt;/strong&gt; 表示。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-002.png"
width="547"
height="315"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-002_hu_172e434a2aaa8214.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-002_hu_798f8df3a9df776d.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="173"
data-flex-basis="416px"
&gt;&lt;/p&gt;
&lt;p&gt;一個Binary Tree, 15的左邊/17, 23, 25的左右其實都是NIL(恩，其實它也是BST)&lt;/p&gt;
&lt;p&gt;回到問題，其實問題的輸入是透過array或list的型式，但這邊LeetCode應該已經妥善處理好建造二元樹的過程了，我們暫且不管它。&lt;br&gt;
我們如何判斷兩個二元樹是否相等呢？&lt;br&gt;
由於相等的前提是&lt;strong&gt;結構相同且所有對應的節點的值&lt;/strong&gt; 也相同，我們勢必要一個一個檢查才能知道結果，所以我們必須要&lt;strong&gt;走訪整棵樹(Tree Traversal&lt;/strong&gt; )。&lt;br&gt;
一個標準的走訪分成四種模式：&lt;br&gt;
&lt;strong&gt;前序、中序、後序以及層序(Pre-order/In-order/Post-order/Level-order)&lt;/strong&gt; 我們這次只會先從最直覺的前序遍歷開始。&lt;/p&gt;
&lt;p&gt;假設如題目所提，我們有兩棵二元樹，他們的root分別是p跟q，&lt;br&gt;
那麼檢查它們是否相等的話，我們要做的事情是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;檢查&lt;strong&gt;p和q是否相等&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;檢查&lt;strong&gt;p的左子樹&lt;/strong&gt; 和&lt;strong&gt;q的左子樹&lt;/strong&gt; 是否相等&lt;/li&gt;
&lt;li&gt;檢查&lt;strong&gt;p的右子樹&lt;/strong&gt; 和&lt;strong&gt;q的右子樹&lt;/strong&gt; 是否相等&lt;br&gt;
唯有這三項均成立，我們才能說p跟q兩棵二元樹相等，否則即為不相等。&lt;br&gt;
接下來，我們先考慮2和3的部分，&lt;br&gt;
其實就等同於&lt;strong&gt;反複拿更小的子樹去做1~3的動作，&lt;br&gt;
直到比對的兩邊當中有不同或空掉的狀況&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我們拿下面的圖為例，可以簡單推論出，&lt;br&gt;
當&lt;strong&gt;檢查兩個節點是否相等&lt;/strong&gt; 的狀況有幾個可確定：&lt;br&gt;
a. 一邊有節點，另一邊沒有節點 =&amp;gt; 結構已經不一樣了，所以&lt;strong&gt;兩棵樹不同&lt;/strong&gt; 。&lt;br&gt;
b. 兩邊均無節點 =&amp;gt; &lt;strong&gt;結構相同&lt;/strong&gt; 且沒有子節點，所以&lt;strong&gt;這個位置的子樹相同&lt;/strong&gt; 。&lt;br&gt;
c. 兩邊都有結點 =&amp;gt; &lt;strong&gt;檢查值是否相同，相同的話，再檢查左右子樹&lt;/strong&gt; 。&lt;br&gt;
(也就是回到上一段那邊的2~3)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-003.png"
width="400"
height="155"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-003_hu_e5816fc1799c9fe2.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-003_hu_bc4442a766dd4eab.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="258"
data-flex-basis="619px"
&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-004.png"
width="400"
height="155"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-004_hu_7a4895d1fcaaca67.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-13-tree-1/image-004_hu_d383091bee898d29.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="258"
data-flex-basis="619px"
&gt;&lt;/p&gt;
&lt;p&gt;所以，我們可以用連續呼叫自己這個解題函式的方式來解決這個問題，&lt;br&gt;
其演算方式可以大致列成這樣：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;isSameTree(p, q) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 若p和q均為NIL，回傳真
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 若p或q為NIL，回傳假(因為表示恰有一個是NIL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 回傳 (p.val==q.val) 且 isSameTree(p.left, q.left) 且 isSameTree(p.right, q.right)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意這樣子的比較，我們每次是&lt;strong&gt;先比較根節點&lt;/strong&gt; ，再比較&lt;strong&gt;左節點&lt;/strong&gt; 的部分，最後才是比較&lt;strong&gt;右節點&lt;/strong&gt; ，同時，每次呼叫isSameTree時，會一路往左邊先找下去，直到左子樹找完了才會走訪右子樹的部分，所以順序是&lt;strong&gt;根-左-右&lt;/strong&gt; ，也就是一般所謂的前序遍歷(Pre-order Traversal)。&lt;/p&gt;
&lt;p&gt;這種不斷呼叫自己來求解的方式，我們稱之為&lt;strong&gt;遞迴(Recursion，或譯遞歸)&lt;/strong&gt; ，這樣的解法一般稱為&lt;strong&gt;遞迴解(Recursive solution)&lt;/strong&gt; ，一般來說還會有另一種解法，主要是透過&lt;strong&gt;額外的資料結構及迴圈&lt;/strong&gt; ，來解決問題，這種方式叫做&lt;strong&gt;迭代法/迭代解(Iterative method/Iterative solution)&lt;/strong&gt; 。比較熟練的讀者若有興趣，可以自行嘗試使用Queue或Deque來解本題看看。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/0d35a8d31b8370b5b726a420b09f376f.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分，由於NIL是用None來表示，&lt;br&gt;
所以檢查可以用if not的方法來處理，且&lt;strong&gt;not運算的優先層級高於and/or&lt;/strong&gt; ，&lt;br&gt;
所以我們不用額外幫它加括號。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/47039932c601895037c316bc7bec1842.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間複雜度/空間複雜度？」&lt;br&gt;
(如果答案為真的話，那麼&lt;strong&gt;每個節點均會走訪一次，故為O(N)&lt;/strong&gt; )&lt;br&gt;
(空間複雜度的話，遞迴同樣會佔用記憶體空間，層數則取決於樹的層數，&lt;br&gt;
如果是平衡樹(balanced tree)的話，因為分布要平衡(填滿)，&lt;br&gt;
每層的節點數量會是1, 2, 4, 8, 16, &amp;hellip;, 總和N=2的n次方-1，n為層數。&lt;br&gt;
所以空間複雜度會是&lt;strong&gt;O(logN)&lt;/strong&gt; ，N為節點的總數。&lt;br&gt;
最差的狀況下，節點全部連在同一邊，那空間複雜度可以達到O(N)。)&lt;/p&gt;
&lt;p&gt;「可以不用遞迴解嗎？」&lt;br&gt;
(可以，有興趣的讀者可以嘗試看看，具體方式是使用Queue或Deque，先將兩個根節點放入，接著每次取出一組節點對；先比較節點，&lt;strong&gt;再將兩樹其左右node成對地放入裡面&lt;/strong&gt; ，重複迴圈，直到有&lt;strong&gt;不相等&lt;/strong&gt; 的狀況產生，或直到&lt;strong&gt;Queue/Deque內再無節點&lt;/strong&gt; 。)&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item></channel></rss>