<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>從LeetCode學演算法 on 跟著 Desolve 學程式</title><link>https://learnwithdesolve.netlify.app/series/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95/</link><description>Recent content in 從LeetCode學演算法 on 跟著 Desolve 學程式</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Wed, 01 May 2024 00:00:00 +0800</lastBuildDate><atom:link href="https://learnwithdesolve.netlify.app/series/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95/index.xml" rel="self" type="application/rss+xml"/><item><title>從LeetCode學演算法-121 (0802. Find Eventual Safe States)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/</link><pubDate>Wed, 01 May 2024 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法-121 (0802. Find Eventual Safe States)" />&lt;h2 id="categories-graphdfs">Categories: Graph/DFS
&lt;/h2>&lt;h2 id="level-medium">Level: Medium
&lt;/h2>&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p>
&lt;p>(3591元有效期限至 2024/05/16 23:59)&lt;br>
&lt;a class="link" href="https://hiskio.com/bundles/egb397?s=tc" target="_blank" rel="noopener"
>https://hiskio.com/bundles/egb397?s=tc&lt;/a>&lt;/p>
&lt;p>(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
>https://bit.ly/lc2022all&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
>https://bit.ly/lc2022adv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>There is a directed graph of &lt;code>n&lt;/code> nodes with each node labeled from &lt;code>0&lt;/code> to &lt;code>n - 1&lt;/code>. The graph is represented by a &lt;strong>0-indexed&lt;/strong> 2D integer array &lt;code>graph&lt;/code> where &lt;code>graph[i]&lt;/code> is an integer array of nodes adjacent to node &lt;code>i&lt;/code>, meaning there is an edge from node &lt;code>i&lt;/code> to each node in &lt;code>graph[i]&lt;/code>.&lt;/p>
&lt;p>A node is a &lt;strong>terminal node&lt;/strong> if there are no outgoing edges. A node is a ** safe node** if every possible path starting from that node leads to a ** terminal node** (or another safe node).&lt;/p>
&lt;p>Return &lt;em>an array containing all the&lt;/em> *&lt;strong>safe nodes&lt;/strong> * &lt;em>of the graph&lt;/em>. The answer should be sorted in &lt;strong>ascending&lt;/strong> order.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001.png"
width="800"
height="228"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu578726b0a7a3bda5b07826adcb966761_91720_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-121-0802-find-eventual-safe-states/image-001_hu578726b0a7a3bda5b07826adcb966761_91720_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="350"
data-flex-basis="842px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [2,4,5,6]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The given graph is shown above.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Nodes 5 and 6 are terminal nodes as there are no outgoing edges from either of them.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Every path starting at nodes 2, 4, 5, and 6 all lead to either node 5 or 6.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Only node 4 is a terminal node, and every path starting at node 4 leads to node 4.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>n == graph.length&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= n &amp;lt;= 104&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= graph[i].length &amp;lt;= n&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= graph[i][j] &amp;lt;= n - 1&lt;/code>&lt;/li>
&lt;li>&lt;code>graph[i]&lt;/code> is sorted in a strictly increasing order.&lt;/li>
&lt;li>The graph may contain self-loops.&lt;/li>
&lt;li>The number of edges in the graph will be in the range &lt;code>[1, 4 * 104]&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h2 id="分析解題">分析/解題
&lt;/h2>&lt;p>有一個有向圖，當中包含了n個節點，每個節點分別被標記為0~n-1。&lt;br>
這個圖使用2D的array graph來表示，&lt;br>
當中graph[i]代表所有從節點i有邊(edge)相連的節點，&lt;br>
且方向是從節點i到每個graph[i]中的節點。&lt;/p>
&lt;p>如果一個節點&lt;strong>沒有任何向外的邊&lt;/strong> 的話，則該節點是&lt;strong>terminal node&lt;/strong> ；&lt;br>
如果從一個節點出去的&lt;strong>所有可能的路徑&lt;/strong> 都&lt;strong>導向到terminal node&lt;/strong> 的話，&lt;br>
則該節點是&lt;strong>safe node&lt;/strong> 。&lt;/p>
&lt;p>試找出所有圖中的safe nodes，並且以陣列(串列)型態回傳，&lt;br>
當中答案必須要以&lt;strong>升冪排序&lt;/strong> (由小到大排列)。&lt;/p>
&lt;p>首先我們要思考的是，怎麼樣的狀況下會沒辦法terminal呢？&lt;br>
按照定義，一旦導到&lt;strong>terminal node&lt;/strong> ，則由於沒有向外的邊，&lt;br>
於是路徑就會停在terminal node了(因為&lt;strong>無路可走&lt;/strong> )。&lt;br>
換句話說，如果要不停下來的話，就要一直有路可走。&lt;br>
但&lt;strong>節點和邊都是有限的&lt;/strong> ，那麼就只有當&lt;strong>存在環&lt;/strong> 的狀況下，&lt;br>
才能夠一直有路可以走囉！&lt;/p>
&lt;p>因此，要判斷一個點是否為safe node，&lt;br>
端看從該點出發的路徑&lt;strong>是否存在有環&lt;/strong> ；&lt;br>
如果有環的話，&lt;strong>則包含該點，以及環上的所有節點都不會是safe node&lt;/strong> 。&lt;/p>
&lt;p>同時，由於我們判斷safe node必須要&lt;strong>所有路徑&lt;/strong> 都沒有環存在，&lt;br>
&lt;strong>因此前面檢查過的節點結果，會同樣適用於後面的檢查&lt;/strong> 。&lt;br>
例如：從點A出發，如果其中一條路徑我們走過點B跟點C，&lt;br>
那麼下次當檢查從點B出發的時候，&lt;br>
我們可以直接採納前面點A出發經過點B時對點B判斷的結果，&lt;br>
如此一來就不用重新再走一遍了！&lt;/p>
&lt;p>那麼這題應該要做的就是遍歷每一個節點及路徑，&lt;br>
並且每條路徑都走到底(或者走到可以判定是否有環)為止，&lt;br>
這顯然適用於DFS的做法。&lt;/p>
&lt;p>讓我們來試著列看看解題步驟：&lt;/p>
&lt;ol>
&lt;li>初始化兩個陣列(串列) &lt;strong>vis, path&lt;/strong> ，分別代表該節點是否已造訪過，&lt;br>
以及該節點是否為某個環的一部分，兩者的長度均為graph的節點數量n，&lt;br>
預設值均為0(或False也可以)。&lt;/li>
&lt;li>初始化一個空的res串列備用。&lt;/li>
&lt;li>宣告一個dfs函式，代入&lt;strong>curr, graph, vis, path&lt;/strong> (curr為要檢查的node)，&lt;br>
其回傳&lt;strong>True則代表存在環，False則代表不存在環&lt;/strong> 。&lt;/li>
&lt;li>在dfs函式中，進行以下處理：&lt;br>
4–1. 將vis[curr]和path[curr]均&lt;strong>設為1&lt;/strong> (也就是已造訪，且&lt;strong>暫定環存在&lt;/strong> )&lt;br>
4–2. 迴圈從&lt;strong>graph[curr]&lt;/strong> 中取出節點u：&lt;br>
4–2–1. 若vis[u]為0 (表示這個節點還沒被造訪) -&amp;gt; &lt;br>
代入到dfs往下檢查，如得到回傳True的話則也回傳True(代表確定有環)&lt;br>
4–2–2. 否則，若&lt;strong>path[u] == 1&lt;/strong> (表示** u在環上**)，回傳True。&lt;br>
4–3. 經過迴圈結束後尚未回傳，代表其實從curr往下走並不存在環，&lt;br>
這時候重新將&lt;strong>path[curr]設為0&lt;/strong> ，並且回傳&lt;strong>False&lt;/strong> 。&lt;br>
(前面直接回傳True的時候，因為我們預先將沿路的path[curr]設為1，&lt;br>
因此離開的時候&lt;strong>整條路徑上的節點都被標記成環了&lt;/strong> ；&lt;br>
反過來說，當發現不存在環的時候，&lt;strong>該還原的就要還原回來&lt;/strong> 。)&lt;/li>
&lt;li>在主函式中，使用迴圈令i依次從&lt;strong>0~n-1&lt;/strong> ，&lt;br>
如果&lt;strong>vis[i] == 0&lt;/strong> 的話，就代入進行dfs。&lt;/li>
&lt;li>都做完的狀況下，再次使用迴圈令i從&lt;strong>0~n-1&lt;/strong> ，&lt;br>
將&lt;strong>path[i] == 0&lt;/strong> 的&lt;strong>i&lt;/strong> 加入到res。&lt;/li>
&lt;li>回傳res。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分使用了ArrayList給res使用，&lt;br>
如果想要讓dfs不要帶入那麼多東西的話，&lt;br>
也可以將vis跟path設定為class variables，&lt;br>
不過因為長度跟graph的節點數掛勾，&lt;br>
所以還是要在eventualSafeNodes裡才能初始化。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/a0d407e4d47566801d4644afb900a168.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分如同以前提到過的，&lt;br>
使用子函式也可以稍微減少需要代入的變數量，&lt;br>
甚至將vis和path放最前面的話也可以連它們都不需要代入，&lt;br>
因為子函式可以去取得到上面這層的變數。&lt;br>
(讀者可以自行嘗試再改寫看看)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/182d787f4f43559379a39a192c1ffe24.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間／空間複雜度？」&lt;br>
(O(V+E)/O(V)，V為graph的節點數，E為graph的邊數)&lt;/p>
&lt;p>「能不能只用一個陣列／串列來處理經過的節點和環？」&lt;br>
(提示：State可以不只有1或0，可以設定3種state來處理)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
>https://bit.ly/lc2022base&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法-120 (0547. Number of Provinces)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/</link><pubDate>Tue, 06 Jun 2023 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法-120 (0547. Number of Provinces)" />&lt;h2 id="categories-graphunion-find">Categories: Graph/Union Find
&lt;/h2>&lt;h2 id="level-medium">Level: Medium
&lt;/h2>&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p>
&lt;p>(3591元 特價中: 2023/06/30 23:59後截止) &lt;br>
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
>https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a>&lt;/p>
&lt;p>(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
>https://bit.ly/lc2022all&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
>https://bit.ly/lc2022adv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>There are &lt;code>n&lt;/code> cities. Some of them are connected, while some are not. If city &lt;code>a&lt;/code> is connected directly with city &lt;code>b&lt;/code>, and city &lt;code>b&lt;/code> is connected directly with city &lt;code>c&lt;/code>, then city &lt;code>a&lt;/code> is connected indirectly with city &lt;code>c&lt;/code>.&lt;/p>
&lt;p>A &lt;strong>province&lt;/strong> is a group of directly or indirectly connected cities and no other cities outside of the group.&lt;/p>
&lt;p>You are given an &lt;code>n x n&lt;/code> matrix &lt;code>isConnected&lt;/code> where &lt;code>isConnected[i][j] = 1&lt;/code> if the &lt;code>ith&lt;/code> city and the &lt;code>jth&lt;/code> city are directly connected, and &lt;code>isConnected[i][j] = 0&lt;/code> otherwise.&lt;/p>
&lt;p>Return &lt;em>the total number of&lt;/em> *&lt;strong>provinces&lt;/strong> *.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO.jpg"
width="222"
height="142"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO_hu7e76285269fea437e0a13eb563307f28_3710_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_gzPQzUPCV6vo5zpO_hu7e76285269fea437e0a13eb563307f28_3710_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo.jpg"
width="222"
height="142"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo_hu5389fdf40733f2780ce3353688c52108_3380_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-120-0547-number-of-provinces/0_vYmD9XAZJEU4Isbo_hu5389fdf40733f2780ce3353688c52108_3380_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= n &amp;lt;= 200&lt;/code>&lt;/li>
&lt;li>&lt;code>n == isConnected.length&lt;/code>&lt;/li>
&lt;li>&lt;code>n == isConnected[i].length&lt;/code>&lt;/li>
&lt;li>&lt;code>isConnected[i][j]&lt;/code> is &lt;code>1&lt;/code> or &lt;code>0&lt;/code>.&lt;/li>
&lt;li>&lt;code>isConnected[i][i] == 1&lt;/code>&lt;/li>
&lt;li>&lt;code>isConnected[i][j] == isConnected[j][i]&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>有n個城市，其中一些城市彼此相連，而另一些則沒有。&lt;br>
如果城市a與城市b直接相連，並且城市b與城市c直接相連，&lt;br>
那麼城市a與城市c之間間接相連。(OS: 好廢話XD)&lt;/p>
&lt;p>一個省(province)是一組直接或間接相連的城市，&lt;br>
且該群組中沒有其他的城市。&lt;br>
(也就是直要可以從x走到y，它們就視為相同省)&lt;/p>
&lt;p>給定一個n x n的矩陣isConnected，&lt;br>
其中isConnected[i][j] = 1表示第i個城市和第j個城市直接相連，isConnected[i][j] = 0則表示它們不直接相連，回傳省的總數量。&lt;/p>
&lt;p>我們已經在&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
>&lt;strong>第115篇&lt;/strong> &lt;/a>以及上一篇中提到了很多Graph的概念，&lt;br>
今天再來仔細一點探討Union Find的用法。&lt;/p>
&lt;p>由於isConnected太長了，我們底下還是直接使用edges來稱呼比較簡便。&lt;br>
首先看到了要找provinces的組數，&lt;br>
顯然又是一個很典型能使用Union Find的場合；&lt;br>
但先前我們提到過，如果只是一路沿著edge往回trace老大的話，&lt;br>
對於單一點的find有可能達到O(n)，&lt;br>
因此我們需要做一些簡化：在&lt;strong>union&lt;/strong> 的合併時，&lt;br>
就盡可能地&lt;strong>先行收斂&lt;/strong> 。那麼我們應該怎麼做呢？&lt;/p>
&lt;p>我們這邊定義一個串列叫做rank，&lt;br>
用以表達每個節點往上對到的root所含有的節點總數。&lt;br>
那麼在合併的時候，有別於先前的任意指定，&lt;br>
我們這次可以選擇先檢查誰的rank大，&lt;br>
接著&lt;strong>人多欺負人少&lt;/strong> &amp;hellip;&amp;hellip;不對，是&lt;strong>rank大的合併掉rank小&lt;/strong> 的群組；&lt;br>
rank小的群組的root要設定為rank大的群組的root。&lt;br>
這麼一來，在合併的過程中，由於一直是大的合併小的，&lt;br>
相對而言會較不容易將union的連接拉太多層，&lt;br>
這個手法我們稱之為&lt;strong>路徑壓縮(path compression)&lt;/strong> 。&lt;/p>
&lt;p>因此，我們的find的寫法和union的寫法會像這樣：&lt;br>
&lt;strong>find(root, i):&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>先取到r = root[i]&lt;/li>
&lt;li>如果r和root[r]不相等(代表還沒走到自己是root(老大)的節點)進行迴圈:&lt;/li>
&lt;li>將root[root[r]]的值塞給root[r]&lt;/li>
&lt;li>令r = root[r] (來到上面一層，繼續準備判斷)&lt;/li>
&lt;li>在2~4的迴圈結束後，直接令root[i] = r，&lt;br>
標明節點i的最上面的老大是r。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>union(root, rank, x, y):&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>對x, y分別使用find，取得各自的root &lt;strong>rx, ry&lt;/strong>&lt;/li>
&lt;li>如果&lt;strong>rx和ry相同&lt;/strong> ，代表已經是同一組了，&lt;strong>直接回傳false&lt;/strong>&lt;/li>
&lt;li>如果不同，則看rank[rx]和rank[ry]的關係，&lt;br>
&lt;strong>rank[rx] ≥ rank[ry]&lt;/strong> 的話，就將&lt;strong>rank[rx]遞增rank[ry]&lt;/strong> ，&lt;br>
並且令&lt;strong>root[ry] = rx&lt;/strong> ；&lt;br>
反之，若&lt;strong>rank[rx] &amp;lt; rank[ry]&lt;/strong> ，則將&lt;strong>rank[ry]遞增rank[rx]&lt;/strong> ，&lt;br>
並且令&lt;strong>root[rx] = ry&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>那麼，剩下來我們只需要做完對root和rank的初始化(&lt;strong>1~n-1&lt;/strong> 跟&lt;strong>1&lt;/strong> )&lt;br>
剩下就是&lt;strong>雙層迴圈&lt;/strong> 對有&lt;strong>edge&lt;/strong> 的兩點呼叫&lt;strong>union&lt;/strong> ，&lt;br>
最後對於每個節點確認它們&lt;strong>不重複的root有哪些&lt;/strong> 即可。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分一樣可以用&lt;strong>Arrays.fill()&lt;/strong> 來設定定值，&lt;br>
同時因為我們union其實沒特別用到true/false的需求，&lt;br>
可以設定為void，直接將對應該改的東西改一改，&lt;br>
並直接return即可。&lt;/p>
&lt;p>同時，在記錄答案時，我們可以使用HashSet，&lt;br>
在最後對i做遍歷並逐個進行find()，並加到當中，&lt;br>
最後檢查res.size()即可得到我們要的答案。&lt;/p>
&lt;p>另外可以留意的是，雙重迴圈的union(i, j)因為沒有方向性的關係，&lt;br>
第二層的j可以&lt;strong>從i+1開始&lt;/strong> 就好，不需要從0開始。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/26aa057a36ea78c2d4511cba41333eeb.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分除了改成用子函式以外，&lt;br>
其餘則大同小異。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/40a58853d50c6c18acded10bee487bac.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
( O(n²)/O(n)，因為即便有經過path的壓縮，遍歷所有edge仍然要O(n²)，&lt;br>
空間的部分則是只需要考慮記錄root和rank的空間)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol start="684">
&lt;li>Redundant Connection (Medium)&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
>https://bit.ly/lc2022base&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 119 Graph (2) / DFS (21)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/</link><pubDate>Sun, 04 Jun 2023 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 119 Graph (2) / DFS (21)" />&lt;p>&lt;strong>0797. All Paths From Source to Target (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p>
&lt;p>(3591元 特價中: 2023/06/30 23:59後截止) &lt;br>
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
>https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a>&lt;/p>
&lt;p>(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
>https://bit.ly/lc2022all&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
>https://bit.ly/lc2022adv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a directed acyclic graph (&lt;strong>DAG&lt;/strong> ) of &lt;code>n&lt;/code> nodes labeled from &lt;code>0&lt;/code> to &lt;code>n - 1&lt;/code>, find all possible paths from node &lt;code>0&lt;/code> to node &lt;code>n - 1&lt;/code> and return them in &lt;strong>any order&lt;/strong> .&lt;/p>
&lt;p>The graph is given as follows: &lt;code>graph[i]&lt;/code> is a list of all nodes you can visit from node &lt;code>i&lt;/code> (i.e., there is a directed edge from node &lt;code>i&lt;/code> to node &lt;code>graph[i][j]&lt;/code>).&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH.jpg"
width="242"
height="242"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH_hu277f25b79bf179da63fbb9fbb0bd626f_7444_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_JZvZO8TcGYlV_krH_hu277f25b79bf179da63fbb9fbb0bd626f_7444_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: graph = [[1,2],[3],[3],[]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [[0,1,3],[0,2,3]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There are two paths: 0 -&amp;gt; 1 -&amp;gt; 3 and 0 -&amp;gt; 2 -&amp;gt; 3.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX.jpg"
width="423"
height="301"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX_hud81ea4d8df4bd22ace96a4abe2dd782b_13566_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-119-graph-2-dfs-21/0_205SEP480YZHWDkX_hud81ea4d8df4bd22ace96a4abe2dd782b_13566_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="140"
data-flex-basis="337px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: graph = [[4,3,1],[3,2,4],[3],[4],[]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>n == graph.length&lt;/code>&lt;/li>
&lt;li>&lt;code>2 &amp;lt;= n &amp;lt;= 15&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= graph[i][j] &amp;lt; n&lt;/code>&lt;/li>
&lt;li>&lt;code>graph[i][j] != i&lt;/code> (i.e., there will be no self-loops).&lt;/li>
&lt;li>All the elements of &lt;code>graph[i]&lt;/code> are &lt;strong>unique&lt;/strong> .&lt;/li>
&lt;li>The input graph is &lt;strong>guaranteed&lt;/strong> to be a ** DAG**.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個有向無環圖(directed acyclic graph, DAG)，&lt;br>
當中有n個nodes，分別被標記為0到n - 1，&lt;br>
找出所有可以從node 0走到node n - 1的路徑，&lt;br>
並且以任意排序的方式回傳。&lt;/p>
&lt;p>graph的給定方式如以下敘述：&lt;br>
graph[i] 代表所有從node i可以造訪的nodes的串列。&lt;br>
(直接造訪，也就是指node i到graph[i][j]之間會有一個有方向的edge(邊))&lt;/p>
&lt;p>我們這篇再來談談graph。&lt;br>
之前我們在&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-115-graph-1-union-find-1-3616ad4a6496" target="_blank" rel="noopener"
>&lt;strong>第115篇&lt;/strong> &lt;/a>提到過，&lt;br>
在graph當中，有方向性的(a -&amp;gt; b和 b -&amp;gt; a被視為不一樣的邊)圖，&lt;br>
被稱為&lt;strong>有向圖(directed graph)&lt;/strong> ；而如果有向圖中，&lt;br>
不存在&lt;strong>環(cycle，也就是圖上存在一個點a，從點a出發，&lt;br>
有一條路徑可以再走回點a)&lt;strong>的話，&lt;br>
則稱為&lt;/strong>有向無環圖&lt;/strong> ，簡寫為DAG。&lt;/p>
&lt;p>既然題目保證圖是DAG，那麼我們從任何一個點出發，&lt;br>
都保證不可能會再回到同一個點，同時也不可能走回頭路，&lt;br>
也就不存在重複的可能。&lt;/p>
&lt;p>讓我們嘗試列出找尋路徑的步驟：&lt;/p>
&lt;ol>
&lt;li>首先從i = 0開始，觀察&lt;strong>graph[i]&lt;/strong> 的連接，&lt;br>
例如像Example 1中0就連到1跟2，&lt;br>
也就是說會有 &lt;strong>0-&amp;gt;1&lt;/strong> 跟&lt;strong>0-&amp;gt;2&lt;/strong> 這兩條路徑&lt;/li>
&lt;li>對於0-&amp;gt;1而言，接下來我們要看1的連接，&lt;br>
發現它只連接到3，而3剛好是這個graph的最後一個節點，&lt;br>
因此得到其中一個有效的路徑是0-&amp;gt;1-&amp;gt;3。&lt;/li>
&lt;li>同理，對於0-&amp;gt;2而言也剛好只有0-&amp;gt;2-&amp;gt;3。&lt;/li>
&lt;/ol>
&lt;p>因此對於這題，我們可以使用DFS從node 0做遞迴往下，&lt;br>
中途要記住每一步當下走過的路徑，只要有走到終點的路徑，&lt;br>
就將其放到答案的列表裡，最後再將整個結果回傳即可。&lt;/p>
&lt;p>列出解題步驟如下：&lt;/p>
&lt;ol>
&lt;li>初始化一個串列res，用以存放結果的路徑&lt;/li>
&lt;li>定義一個dfs的函式，輸入為**(i, path)** ，&lt;br>
當中i為當前走到的node，path為走到node i時經過的路徑(&lt;strong>包含i&lt;/strong> )。&lt;/li>
&lt;li>在函式中，首先檢查i是否和graph的長度-1相等，&lt;br>
如是，代表走到&lt;strong>node n-1&lt;/strong> 的位置了，&lt;br>
&lt;strong>該路徑是答案之一，將其加到res上&lt;/strong> 。&lt;/li>
&lt;li>若3的檢查解果為否，代表要繼續往下走，&lt;br>
迴圈遍歷&lt;strong>graph[i]&lt;/strong> 中的下一個node nxt，&lt;br>
並呼叫dfs，將&lt;strong>node nxt&lt;/strong> 和新的path(&lt;strong>path加上nxt&lt;/strong> )代入遞迴。&lt;/li>
&lt;li>將**(0, [0])** 代入dfs中開始遞迴。&lt;/li>
&lt;li>完成5後，將res回傳即可。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>在Java的部分，我們的res顯然是二維的，&lt;br>
因此我們可以使用ArrayList來放入其中。&lt;br>
在helper(或dfs)中，因為不能像Python使用子函式，&lt;br>
這邊參數就需要graph、i、path、res；&lt;br>
又因為path是反覆遞迴下去利用的，&lt;br>
我們在記錄時使用backtracking的方式，&lt;br>
選擇在每次進入helper函式時，將path給加上當前走到的node i，&lt;br>
在離開時，則要記得將其收回，因此分別會在頭尾做&lt;strong>path.add(i)&lt;/strong> ，&lt;br>
以及&lt;strong>path.remove(path.size()-1)&lt;/strong> 。&lt;/p>
&lt;p>其他要留意的部分是，由於在放到res的時候，&lt;br>
對於ArrayList來說是一個指向性質的放置，並不會直接複製一份path，&lt;br>
所以在res.add的時候，必須要使用&lt;strong>new ArrayList(path)&lt;/strong> 的手法，&lt;br>
將path複製一份出來才行；不然後面我們在backtracking的時候，&lt;br>
就會同步影響到res的結果喲！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/f8e5a08fab8cce5a8c5118d8725791b7.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>在Python的部分由於可以使用子函式，&lt;br>
我們可以不需要再將res跟graph加到參數，&lt;br>
就會簡潔一點；&lt;br>
同時，在進行dfs的時候，我們這邊改成用&lt;br>
&lt;strong>path + [nxt]&lt;/strong> 的方式，就會直接形成一個新的list。&lt;br>
這樣一來，path的部分就不需要再回頭處理backtracking的問題，&lt;br>
同時res也可以直接進行append(path)，不需要另行複製。&lt;br>
(因為前面path + [nxt]時已經複製完path並形成一個新的list了)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/edc9788f87792c4c6dc14a112f7ee51a.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(V * 2^V)，因為單一條最多是O(V)，最多可能有O(2^V)條)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
>https://bit.ly/lc2022base&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 — 格式變更</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-format-change/</link><pubDate>Sun, 04 Jun 2023 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-format-change/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 — 格式變更" />&lt;h2 id="該來個改版了">該來個改版了!
&lt;/h2>&lt;p>話說筆者心血來潮搜尋了一下自己的文章，&lt;br>
發現Medium上按照現有的格式，&lt;br>
其實subtitle(副標題)的部分根本不會進入到搜尋的Title中，&lt;br>
這點感覺對於讀者搜尋很不方便XD&lt;/p>
&lt;p>(雖然第0篇都有放連結，老讀者懂得都懂)&lt;/p>
&lt;p>考量過後，將格式調整如下：&lt;br>
Titlte: 從LeetCode學演算法-120 (0547. Number of Provinces)&lt;br>
Subtitle: Categories: Graph/Union Find, Level: Medium&lt;/p>
&lt;p>調整過後，讀者可以清晰看見該篇的題號，&lt;br>
而subtitle會列出題目的種類和難度(就不列是種類的第幾篇了，因為在Medium中沒辦法直接連結搜尋相同個作者的特定tag)。&lt;/p>
&lt;p>另外，因應這個國際化的社會(?)，&lt;br>
接下來的每一篇文章都會提供英文版本，&lt;br>
&lt;strong>英文版本只會往英語系的Python或Coding相關的FB社團發文&lt;/strong> ，&lt;br>
同時不會列到第0篇文章。&lt;/p>
&lt;p>以上調整，不溯及既往，並且從本篇文章起即刻生效，&lt;br>
感謝大家的理解與支持XD!&lt;/p></description></item><item><title>從LeetCode學演算法 - 118 DFS (20) /BFS (5) / Queue (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/</link><pubDate>Sun, 28 May 2023 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 118 DFS (20) /BFS (5) / Queue (6)" />&lt;p>&lt;strong>0934. Shortest Bridge (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南**&lt;/p>
&lt;p>(3591元 特價中: 2023/06/30 23:59後截止) &lt;br>
&lt;a class="link" href="https://hiskio.com/bundles/eCP23B397?s=tc" target="_blank" rel="noopener"
>https://hiskio.com/bundles/eCP23B397?s=tc&lt;/a>&lt;/p>
&lt;p>(3990元 長期有效) &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
>https://bit.ly/lc2022all&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
>https://bit.ly/lc2022adv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are given an &lt;code>n x n&lt;/code> binary matrix &lt;code>grid&lt;/code> where &lt;code>1&lt;/code> represents land and &lt;code>0&lt;/code> represents water.&lt;/p>
&lt;p>An &lt;strong>island&lt;/strong> is a 4-directionally connected group of &lt;code>1&lt;/code>&amp;rsquo;s not connected to any other &lt;code>1&lt;/code>&amp;rsquo;s. There are ** exactly two islands** in &lt;code>grid&lt;/code>.&lt;/p>
&lt;p>You may change &lt;code>0&lt;/code>&amp;rsquo;s to &lt;code>1&lt;/code>&amp;rsquo;s to connect the two islands to form &lt;strong>one island&lt;/strong> .&lt;/p>
&lt;p>Return &lt;em>the smallest number of&lt;/em> &lt;code>0&lt;/code>&lt;em>&amp;rsquo;s you must flip to connect the two islands&lt;/em>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: grid = [[0,1],[1,0]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: grid = [[0,1,0],[0,0,0],[0,0,1]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: grid = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>n == grid.length == grid[i].length&lt;/code>&lt;/li>
&lt;li>&lt;code>2 &amp;lt;= n &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>grid[i][j]&lt;/code> is either &lt;code>0&lt;/code> or &lt;code>1&lt;/code>.&lt;/li>
&lt;li>There are exactly two islands in &lt;code>grid&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個 n x n 的 binary 矩陣 grid，當中 1 代表陸地，0 代表水。&lt;br>
一個 island (島嶼) 的定義是指一組在四個方向和其他的1相連的群組，&lt;br>
且沒有再和其他1相連(也就是中間經過1的都算是同一塊島嶼)。&lt;br>
在 grid 中恰好兩塊島嶼。&lt;br>
你可以將0變成1用來連接兩塊島嶼，以形成一塊島嶼，&lt;br>
試回傳要翻轉0到1使得兩塊島嶼連接的最少所需的數目。&lt;/p>
&lt;p>好久不見了！&lt;/p>
&lt;p>這題算是比較特別的題目，因為比較好的解法會是DFS和BFS都用上，&lt;br>
一個用來找到第一整塊島嶼，另一個用來連接。&lt;/p>
&lt;p>就題目而言，從0翻到1，其實就是一個搭橋的概念，&lt;br>
單就grid上考慮，那麼我們肯定是從兩個島距離最近的點來搭會最好，&lt;br>
但怎麼知道哪兩個點距離最近呢？&lt;/p>
&lt;p>如果兩塊島嶼都是完整矩形的話，&lt;br>
或許我們還可以從邊與邊的垂直距離來做文章，&lt;br>
也還有一些比較簡單的計算方法(比如下圖取兩點的垂直+水平距離)&lt;br>
(如果水平或垂直方向有重合的話則只計di或dj)&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_jDGWMo9GGc6i3QMe20gCKg.png"
width="542"
height="406"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_jDGWMo9GGc6i3QMe20gCKg_huca96ca06ca30b7f41546b2f5bc98b2c7_5024_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_jDGWMo9GGc6i3QMe20gCKg_huca96ca06ca30b7f41546b2f5bc98b2c7_5024_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
>&lt;/p>
&lt;p>取最近的兩點垂直距離+水平距離(也有可能其中一個方向不用計)&lt;/p>
&lt;p>但.…..它們並不一定是矩形XD&amp;quot;&lt;br>
所以有可能出現像這樣子的狀況，然後旁邊可能全是不規則形狀，&lt;br>
無法用矩形算完：&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_YyE0BEXcAeg-8lZKxMERwQ.png"
width="543"
height="407"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_YyE0BEXcAeg-8lZKxMERwQ_hu85ff3733efb085a7c7609bbf1daceaaa_2721_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-118-dfs-20-bfs-5-queue-6/1_YyE0BEXcAeg-8lZKxMERwQ_hu85ff3733efb085a7c7609bbf1daceaaa_2721_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
>&lt;/p>
&lt;p>看圖會知道算哪個點，但究竟要娶幾個點才能算呢？&lt;/p>
&lt;p>所以既然無法知道兩塊島嶼長什麼樣子，也不知道規不規則，&lt;br>
那只能回到笨方法了：&lt;br>
&lt;strong>先找到其中一塊島嶼，再從這塊島嶼的邊界往外找(搭橋)。&lt;/strong>&lt;/p>
&lt;p>我們嘗試來列出解題步驟：&lt;/p>
&lt;ol>
&lt;li>取得grid的長寬r, c (沒錯，這題其實就算不是正方形的grid應該也可以做)&lt;/li>
&lt;li>先遍歷找到grid上任意一個值為1的點(i, j)，&lt;br>
這個點肯定是其中一塊島上的陸地&lt;/li>
&lt;li>從(i, j)開始進行DFS往四方探索陸地，同時將所有途經的陸地標為2&lt;br>
(標成2的意義是為了可以和另一塊島嶼的陸地區分開來)；&lt;/li>
&lt;li>在步驟3的探索中，如果碰到0時，&lt;br>
把和0相接的陸地座標記到一個&lt;strong>queue&lt;/strong> 裡面&lt;br>
(代表這是第一塊陸地的臨水的邊界)&lt;/li>
&lt;li>完成3, 4後，我們會得到一個queue，當中全是第一個島嶼的&lt;strong>臨水的邊界&lt;/strong> ，&lt;br>
作為我們搭橋的出發點，這裡設定我們要求的答案step為0&lt;/li>
&lt;li>當queue中有值的時候，持續操作以下步驟：&lt;/li>
&lt;li>取得當前queue的長度L，進行一個L次的迴圈：&lt;/li>
&lt;li>從queue中取出一組座標(i, j)&lt;/li>
&lt;li>從(i, j)往四個方向看，如果沒有超出grid的話，檢查以下可能：&lt;br>
9-1. 如果值是1，則代表成功接通，這時候直接回傳step作為答案即可&lt;br>
9-2. 如果值是0，則代表繼續搭橋，將新座標放到queue當中，&lt;br>
並且將這個位置的值標為-1(代表已經走過了)&lt;/li>
&lt;li>步驟7的迴圈結束後，將step遞增1，接下來回到6檢查是否要繼續&lt;/li>
&lt;li>雖然題目設定上一直都是找得到解答的，但如果找不到解答的話，&lt;br>
離開步驟6的迴圈後，則應該要回傳-1，表示找不到能搭建的橋&lt;br>
(也就是grid可能被給成只有一塊土地)&lt;/li>
&lt;/ol>
&lt;p>在上面的解題步驟中，步驟3&lt;del>4是&lt;strong>DFS&lt;/strong> ，&lt;br>
目的在於要找到第一塊島嶼，記錄邊界，&lt;br>
並將其值改動成2，用來跟第二塊島嶼區別；&lt;br>
而步驟6&lt;/del>10則是&lt;strong>BFS&lt;/strong> ，&lt;br>
用來從邊界開始往外嘗試搭橋，&lt;br>
因此我們可以在找到連接到第二塊島嶼的時候，&lt;br>
因為一次是每種可能都走一步的特性，確定最小所需的步數，&lt;br>
也就是我們所要求的答案。&lt;/p>
&lt;p>依此，寫成程式碼如下。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>為求簡單，這邊我們直接將grid改名為A，避免寫太多次。&lt;br>
我們可以利用簡單的dirs串列來標定四個方向，&lt;br>
從而縮減每次寫+1和-1的部分，&lt;br>
這個小技巧應該常碰到類似題目的同學大多看過。&lt;br>
另外，我們使用了一個set start，用來幫我們自動化簡加入的座標，&lt;br>
因為我們有可能加同樣的座標到queue裡面，&lt;br>
使用set可以有效避免這一點。&lt;/p>
&lt;p>同時請留意到當A[x][y] == 0的時候，要加入的是(i, j)歐!&lt;br>
因為我們加入的是陸地的邊界(1)，而不是水(0)，&lt;br>
同理，後面起始的時候因為是從陸地開始起算，&lt;br>
所以step是從0而非從1開始。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/4499fef61fa66238f3dc5f9bd440a703.js">&lt;/script>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分則會稍微麻煩一點，&lt;br>
這邊將大多數的東西放在class variable的位置，&lt;br>
可以有效避免需要大量的傳遞參數；&lt;br>
Queue的部份我們使用ArrayDeque來處理，&lt;br>
那麼對應的取出和放入就會變成poll()和offer()。&lt;br>
(注意每次放入的時候都要產生一個新的int[]來放入)&lt;/p>
&lt;p>另一方面，由於HashSet在Java當中用起來比較沒有像Python這麼彈性，&lt;br>
這邊採用visited的方式來處理，&lt;br>
我們將已經放入過q的(i, j)在visited中設定為true，&lt;br>
再每次檢查，即可得到相同效果。&lt;br>
此外，由於Java不接受回傳一個沒有回傳值的function，&lt;br>
因此27和28行會分成兩行來寫，先進行dfs完，再呼叫return。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/41cfb3a3f64ec5a73184e9e68eb92667.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n²)/O(n²)，在長和寬均為n的狀況下，最多也就是掃完整個grid)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
>https://bit.ly/lc2022base&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 優惠資訊</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-you-hui-zi-xun/</link><pubDate>Sat, 04 Jun 2022 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-you-hui-zi-xun/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 優惠資訊" />&lt;p>&lt;strong>下周二(6/7)開始有從LeetCode學演算法全套組合的優惠~&lt;/strong>&lt;/p>
&lt;p>&lt;a class="link" href="https://l.facebook.com/l.php?u=https%3A%2F%2Fhiskio.com%2Fbundles%2FeMF22B397%3Fs%3Dtc%26fbclid%3DIwAR3GI0JPLrGh-TkXWHBMD79OFbLNqIDrFUCtAdZk9ZmAA0uWIT454s5l-Mk&amp;amp;h=AT1gmW70lJXmW79LuXssrAUkUMCa49lysBFDp5-hSeoWDScV8KXZ4cDhlKJ7mLqeU69wf73CNY1QfGRSIBF_SpmTv7lhVT5tEBpFuTya1v-b33SD3joHWE8_Vzc3TOqM5qIVuCwokE3w9tqbUQ&amp;amp;__tn__=R]-R&amp;amp;c[0]=AT0anRcDHTtWGI6t8eGExTxs1h93VhG0b5sVBzrx4SVou36d_LuD3qFKit2tHBlOP6jjEIBSryXRL47IeplArcitPGY5cgN6cTddYI0UQLUsw3QMFPurzbM6capB0YEKCmReyyW1ferZlLAs9yQ3ubLKg6oBJTatjPMqcnz7HK0-2-rI0TCmdLPn4ppbsEuU1-whreVa1wFQ" target="_blank" rel="noopener"
>https://hiskio.com/bundles/eMF22B397?s=tc&lt;/a>&lt;/p>
&lt;p>全套組合特惠價3591元！有興趣的朋友可以參考XD&lt;/p></description></item><item><title>從LeetCode學演算法 - 117 Array (17)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-117-array-17/</link><pubDate>Sun, 30 Jan 2022 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-117-array-17/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 117 Array (17)" />&lt;p>&lt;strong>0941. Valid Mountain Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>2022/03/09: 配合官方修改格式，各項優惠連結3/14之後會失效，&lt;br>
這邊更新新版的連結給大家~**&lt;/p>
&lt;p>&lt;strong>從 LeetCode 學演算法｜完整解題技巧 + 面試成功指南：&lt;/strong> &lt;a class="link" href="https://bit.ly/lc2022all" target="_blank" rel="noopener"
>https://bit.ly/lc2022all&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022adv" target="_blank" rel="noopener"
>https://bit.ly/lc2022adv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of integers &lt;code>arr&lt;/code>, return &lt;code>true&lt;/code> &lt;em>if and only if it is a valid mountain array&lt;/em>.&lt;/p>
&lt;p>Recall that arr is a mountain array if and only if:&lt;/p>
&lt;ul>
&lt;li>&lt;code>arr.length &amp;gt;= 3&lt;/code>&lt;/li>
&lt;li>There exists some &lt;code>i&lt;/code> with &lt;code>0 &amp;lt; i &amp;lt; arr.length - 1&lt;/code> such that:&lt;/li>
&lt;li>&lt;code>arr[0] &amp;lt; arr[1] &amp;lt; ... &amp;lt; arr[i - 1] &amp;lt; arr[i]&lt;/code>&lt;/li>
&lt;li>&lt;code>arr[i] &amp;gt; arr[i + 1] &amp;gt; ... &amp;gt; arr[arr.length - 1]&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-117-array-17/0__l8cBax99BYE7Ikv.png"
width="800"
height="505"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-117-array-17/0__l8cBax99BYE7Ikv_hu152968f845fa7c3f982b83670f38d41d_38947_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-117-array-17/0__l8cBax99BYE7Ikv_hu152968f845fa7c3f982b83670f38d41d_38947_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="158"
data-flex-basis="380px"
>&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [2,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [3,5,5]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [0,3,2,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= arr.length &amp;lt;= 104&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= arr[i] &amp;lt;= 104&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個整數陣列arr，若且唯若它是一個合格的mountain array時，&lt;br>
回傳true(否則回傳false)。&lt;br>
mountain array的條件要符合以下幾點:&lt;/p>
&lt;ol>
&lt;li>arr長≥3&lt;/li>
&lt;li>存在i，0&amp;lt;i&amp;lt;arr.length-1使得:&lt;br>
arr[0] &amp;lt; arr[1] &amp;lt; … &amp;lt; arr[i-1] &amp;lt; arr[i] 且&lt;br>
arr[i] &amp;gt; arr[i + 1] &amp;gt; … &amp;gt; arr[arr.length-1]&lt;/li>
&lt;/ol>
&lt;p>為了避免大家隔太久沒有練習(我也是)，而且快過年了不要讓大家太燒腦，&lt;br>
今天我們就介紹簡單一點的題目就好XD！&lt;/p>
&lt;p>在LeetCode的題型中，有一些簡單的題目的規格，&lt;br>
會呈現為只要題目讀得懂，按要求做完就會答對的形式，&lt;br>
本題就是相當明確的例子之一。&lt;/p>
&lt;p>我們來看看要求：mountain array&lt;br>
前面必須要&lt;strong>嚴格遞增&lt;/strong> ，後面必須要&lt;strong>嚴格遞減&lt;/strong> ，&lt;br>
中間的arr[i]值為整個陣列的最高點。&lt;br>
同時限制了長度必須大於等於3，也就是上下坡都必然存在。&lt;/p>
&lt;p>那麼解題方式就很明確了：&lt;/p>
&lt;ol>
&lt;li>先檢查長度是否≥3，且arr[0]是否小於arr[1]&lt;br>
(一定要檢查，因為我們希望&lt;strong>上下坡都存在&lt;/strong> )&lt;/li>
&lt;li>從陣列的開頭開始以i計數，往後沿途比較arr[i]跟arr[i+1]，&lt;br>
一路遞增到遞減轉折出現為止(也就是第一個arr[i] &amp;gt;arr[i+1])&lt;/li>
&lt;li>在2當中如果出現&lt;strong>前後相等&lt;/strong> 的狀況可直接回傳False，&lt;br>
同時，如果&lt;strong>還沒下坡就已經走到底(i + 1 == arr.length)&lt;/strong> 的話，&lt;br>
也要回傳&lt;strong>False&lt;/strong> 。&lt;/li>
&lt;li>沿路下坡，一路走到尾端&lt;/li>
&lt;li>如果沿途均符合的話(會走到&lt;strong>i + 1 == arr.length&lt;/strong> )，則回傳true；&lt;br>
如果沿途變平或上坡的話，需在4的位置提早停下，&lt;br>
這樣子就可以藉由是否走到尾端這點來判斷要回傳true或false。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>可以看到我們在上坡的時候使用迴圈，&lt;br>
每次檢查就做兩件事來確認是否離開迴圈：&lt;/p>
&lt;ol>
&lt;li>是不是走到底了 -&amp;gt; 走到底的話就不對了，因為還沒下坡&lt;/li>
&lt;li>是不是有在走上坡 -&amp;gt; 變平的話不對，只有變下坡可以接受&lt;/li>
&lt;/ol>
&lt;p>而下坡時只有一路下坡走到底可以被接受。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/2e0e87626e17ebc1f4729134c817fd7e.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python寫法基本上一致，所以說這題不難，對吧XD！&lt;br>
關鍵還是在於是否能確切釐清題目要求，&lt;br>
例如如果沒有寫A[0] ≥ A[1]的檢查的話，&lt;br>
就有可能碰到只有下坡的陣列，從而讓檢查結果出問題喲！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/81650fdb8adc9337e9ebe7f963469467.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，這題最多需要掃完整個陣列，&lt;br>
且我們只有多使用一個i的變數。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/lc2022base" target="_blank" rel="noopener"
>https://bit.ly/lc2022base&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 — 雜談及促銷活動XD！</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-za-tan-ji-cu-xiao-huo-dong-xd/</link><pubDate>Wed, 08 Dec 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-za-tan-ji-cu-xiao-huo-dong-xd/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 — 雜談及促銷活動XD！" />&lt;p>&lt;strong>還在等折價嗎？這不就來了嗎XD&lt;/strong>&lt;/p>
&lt;p>即日起開始有配合HiSKIO官方的折價活動，&lt;br>
整包課程活動價只要3591元，&lt;br>
新的一年，投資自己練功，為自己加值戰力！&lt;br>
有興趣的朋友可以參考看看~&lt;br>
&lt;a class="link" href="https://hiskio.com/packages/1AyXD1oyQ" target="_blank" rel="noopener"
>https://hiskio.com/packages/1AyXD1oyQ&lt;/a>&lt;/p>
&lt;p>由於事情比較多的關係，一直打不起精神寫新的文章，真是不好意思QQ&lt;br>
雜談一下，這段時間以來，大體上就是在了解加密貨幣相關的基本知識(真的很基本的那種)，以及換工作(大誤)，還有做之前鐵人賽得名的從零開始學Python，在博碩文化出版為&lt;a class="link" href="https://www.tenlong.com.tw/products/9789864348503" target="_blank" rel="noopener"
>&lt;strong>初學 Python 的第一本書 : 從基本語法到模組應用&lt;/strong> &lt;/a>，在天瓏書局或博客來都有販售，當然也有電子書版本，打完折應該都算打到骨折啦，同時也邀請到了&lt;strong>葉丙成老師(對，是各位想的那位葉丙成)&lt;/strong> 做封面推薦，以及&lt;strong>HiSKIO的創辦人Adam&lt;/strong> 來寫序。&lt;/p>
&lt;p>這邊要說一點實話，其實完書後我是覺得還存在一些不足的，儘管我某種程度上很嚴苛地對待第一本出版的著作，但有限的時間內，其實只允許我盡可能將錯字和排版錯誤等問題排除，以及程式碼不要有錯漏的問題，還有增加一些基本的習題，希望能協助新手每個環節都能練習到基本Python使用的方法和觀念。沒記錯的話，跟線上的文章差異應該僅有幾個小節的新增，而沒有大幅度的變化。&lt;/p>
&lt;p>所以如果你問我說：「我想支持你，買一本你的書怎麼樣？」的時候，我會很感激，然後拜託你買課我會賺比較多XD&lt;br>
當然，畢竟是第一本書，所以真的願意花錢購買支持的讀者，我也是真的相當感謝，希望額外的修改以及適當的排版能幫助你/妳能更好的吸收。&lt;/p>
&lt;p>扣掉這些時間以外，其實說真的我就沒做些什麼事情了，前陣子家裡的貓突然心臟病發作併發肺炎，送醫院進氧氣倉，還沒等到我們轉診送去更專門救治毛小孩心臟病的專科就沒撐過來過世了。哭了一陣然後故作堅強好像是入了社會的人的基本技能，本來還想好結婚的時候一定要讓牠走紅毯當我們的花童的，沒想到牠等不到那天了。世事無常，變化太快，只能且行且珍惜。也請大家要保重身體，以及珍惜和身邊的人相處的時光，不要到最後才後悔。&lt;/p>
&lt;p>扯遠了，拉回來一下。&lt;br>
總之，如果還沒有購買課的讀者，可以把握這次的優惠，&lt;br>
相關的介紹會放在下面。之後會盡量找時間繼續寫文章，就再請大家多多支持囉。&lt;/p>
&lt;p>相關介紹：&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 116 Tree (21) / DFS (19)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/</link><pubDate>Tue, 21 Sep 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 116 Tree (21) / DFS (19)" />&lt;p>&lt;strong>0814. Binary Tree Pruning (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>(基礎+進階+面試篇) 從 LeetCode 學演算法 + 面試成功指南**&lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>新書(第一本，不曉得會不會是最後一本XD)開始預購啦！&lt;br>
&lt;strong>初學 Python 的第一本書 : 從基本語法到模組應用（iT邦幫忙鐵人賽系列書）&lt;/strong> &lt;a class="link" href="https://www.tenlong.com.tw/products/9789864348503" target="_blank" rel="noopener"
>https://www.tenlong.com.tw/products/9789864348503&lt;/a>&lt;br>
這本書主要是針對初學Python的入門讀者，希望能夠提供一個得以從零開始上手，又不會太過冗長的入門學習書。有興趣的話請多多支持！&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given the &lt;code>root&lt;/code> of a binary tree, return &lt;em>the same tree where every subtree (of the given tree) not containing a&lt;/em> &lt;code>1&lt;/code> &lt;em>has been removed&lt;/em>.&lt;/p>
&lt;p>A subtree of a node &lt;code>node&lt;/code> is &lt;code>node&lt;/code> plus every node that is a descendant of &lt;code>node&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz.png"
width="800"
height="224"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz_hu5c504fe605d159eba5decedfae252b4b_43311_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5zTxC9JnDF8GRDhz_hu5c504fe605d159eba5decedfae252b4b_43311_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="357"
data-flex-basis="857px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,null,0,0,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,null,0,null,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Only the red nodes satisfy the property &amp;#34;every subtree not containing a 1&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The diagram on the right represents the answer.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU.png"
width="800"
height="184"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU_hu28d65b925bb6cc1e5fb8099aa440af03_47219_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_E1Tq4_L1vjGx8RqU_hu28d65b925bb6cc1e5fb8099aa440af03_47219_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="434"
data-flex-basis="1043px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,0,1,0,0,0,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,null,1,null,1]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x.png"
width="800"
height="215"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x_hu19656392e0bb7cb020139aa317202e15_61308_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-116-tree-21-dfs-19/0_5yuz2kYgJcGvgU2x_hu19656392e0bb7cb020139aa317202e15_61308_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="372"
data-flex-basis="893px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,1,0,1,1,0,1,0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,1,0,1,1,null,1]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>The number of nodes in the tree is in the range &lt;code>[1, 200]&lt;/code>.&lt;/li>
&lt;li>&lt;code>Node.val&lt;/code> is either &lt;code>0&lt;/code> or &lt;code>1&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹的root，將同一棵樹中未含任何1的子樹均去除掉並回傳。&lt;br>
(限制條件：樹的節點數目在1~200之間，且Node的值只會是0或1)&lt;/p>
&lt;p>如果我們看到範例的話，大致上可以理解要被去掉的部分就是包括自己以及其底下的所有節點值均為0的子樹，這樣才能保證剩下的符合題目要求的條件。&lt;/p>
&lt;p>因此，我們總體要做的就是檢查一棵樹的左子樹及右子樹狀況，&lt;br>
然後分別決定左子樹/右子樹是否要被去掉，最後將當棵樹的總體狀況往上回傳，因此，設計一個子函數helper如下：&lt;/p>
&lt;ol>
&lt;li>傳入要檢查的節點n&lt;/li>
&lt;li>如果n是空節點，則直接回傳0(因為這代表往下左右沒有其它節點了，也不用繼續檢查)&lt;/li>
&lt;li>遞迴檢查左子樹(將n.left代入helper)，取得左子樹含1的節點數量為l&lt;/li>
&lt;li>遞迴檢查右子樹(將n.right代入helper)，取得右子樹含1的節點數量為r&lt;/li>
&lt;li>若l為0，表示無左子樹或左子樹均無節點值為1的節點，將n.left設為NIL&lt;/li>
&lt;li>同理，若r為0，將n.right設為NIL&lt;/li>
&lt;li>回傳l+r+n.val&lt;/li>
&lt;/ol>
&lt;p>在將root代入helper遞迴結束後，所有root的子樹應該都被清乾淨了，&lt;br>
除了root自己以外，所以我們要檢查helper得到的最後的值，&lt;br>
若為0的話，則最終我們應回傳NIL，否則應回傳root。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分使用三元運算子來處理最後的c，&lt;br>
其實我們也可以將整個helper的函式使用True/False來處理，&lt;br>
這樣中間的計算就要改成or來檢查是否至少存在一個節點值為1的節點。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e76ff62f67e0540792c41c7ae6b3fa6e.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分使用子函數來簡單處理，其它的部分邏輯一樣。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/6ebdc845996a04c178cd6a6e2c727b1b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，N為節點總數，總體的遞迴深度則和樹的高度一致。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 115 Graph(1) / Union Find (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/</link><pubDate>Sun, 04 Jul 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 115 Graph(1) / Union Find (1)" />&lt;p>&lt;strong>0684. Redundant Connection (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>從 LeetCode 學演算法 + 面試成功指南**&lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>In this problem, a tree is an &lt;strong>undirected graph&lt;/strong> that is connected and has no cycles.&lt;/p>
&lt;p>You are given a graph that started as a tree with &lt;code>n&lt;/code> nodes labeled from &lt;code>1&lt;/code> to &lt;code>n&lt;/code>, with one additional edge added. The added edge has two &lt;strong>different&lt;/strong> vertices chosen from &lt;code>1&lt;/code> to &lt;code>n&lt;/code>, and was not an edge that already existed. The graph is represented as an array &lt;code>edges&lt;/code> of length &lt;code>n&lt;/code> where &lt;code>edges[i] = [ai, bi]&lt;/code> indicates that there is an edge between nodes &lt;code>ai&lt;/code> and &lt;code>bi&lt;/code> in the graph.&lt;/p>
&lt;p>Return &lt;em>an edge that can be removed so that the resulting graph is a tree of&lt;/em> &lt;code>n&lt;/code> &lt;em>nodes&lt;/em>. If there are multiple answers, return the answer that occurs last in the input.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf.jpg"
width="222"
height="222"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf_hu23ff89227a3d8b07db6971e9c5df8bf5_5001_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_m69nQSg0Xz1tu5mf_hu23ff89227a3d8b07db6971e9c5df8bf5_5001_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: edges = [[1,2],[1,3],[2,3]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [2,3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584.jpg"
width="382"
height="222"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584_hu22b5421fe8abe1e029c5e6bc049c927f_7166_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-115-graph-1-union-find-1/0_saAjSjHo_CMHr584_hu22b5421fe8abe1e029c5e6bc049c927f_7166_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="172"
data-flex-basis="412px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,4]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>n == edges.length&lt;/code>&lt;/li>
&lt;li>&lt;code>3 &amp;lt;= n &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>edges[i].length == 2&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= ai &amp;lt; bi &amp;lt;= edges.length&lt;/code>&lt;/li>
&lt;li>&lt;code>ai != bi&lt;/code>&lt;/li>
&lt;li>There are no repeated edges.&lt;/li>
&lt;li>The given graph is connected.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>在這個問題中，一棵樹是一個無向圖(undirected graph)，且當中沒有環(cycle)。給定一個圖，當中有n個node，標記為從1到n，其中有多一個邊(edge)；多出來的邊是由1到n選出兩個不同的節點(vertices, vertex的複數)所構成的，且並非已經存在的邊。這個圖是由一個長度為n的陣列edges來表示的，其每個元素edges[i]=[ai, bi]表示在圖中，ai和bi兩個節點中間有一個邊連結。&lt;/p>
&lt;p>請回傳一個可以在移除後令這個圖可以形成一棵含有n個節點的樹的邊，如果有多個答案的話，請回傳讓其發生在最後的輸入。&lt;/p>
&lt;p>好的，光翻譯題目就是一個很麻煩的事情，這也是為什麼從之前到現在始終不太想作圖(graph)相關的文章：因為實在太麻煩了，且不好解釋XD&lt;/p>
&lt;p>那我們今天就來挑戰看看吧！希望在看完本篇文章以後，大家還醒著(笑)XD&lt;/p>
&lt;p>在解這題之前，我們應該要先對圖作一點基本介紹：&lt;br>
圖(graph)是一種描述資料與資料之間的連結(不是人與人之間的)的結構，&lt;br>
當中最主要會分為兩個主要的元素：vertex(節點)及edge(邊/線段)。&lt;br>
節點可能擁有自己的一些屬性或值，這個可以依照定義而改變，而節點和節點之間，則是透過邊來連接，因此在同一張圖內，如果有超過一個節點，那它們至少要有能夠相連的邊連結彼此(不然就不會是同一張圖了！)。&lt;/p>
&lt;p>接下來另一個很重要的點是，圖可以分為&lt;strong>有向圖(directed graph)&lt;/strong> 和&lt;strong>無向圖(undirected graph)&lt;/strong> ，什麼意思呢？&lt;/p>
&lt;p>舉例來說，筆者對台北還不夠熟悉的時候，騎著機車在台北附近總是容易繞一大圈才走到自己的目的地，而且回程的時候還容易繞錯路，其中一個原因就是&lt;strong>單行道&lt;/strong> 。單行道表示了今天從A走到B可能可以走XX路，但從B到A可能要走OO路接RR路才行，因為XX路是單向的；換句話說，當從A到B和從B到A無法等價看待的時候，我們會稱這樣的圖為有向圖，因為其關連性不能夠直接反過來也成立。這種圖在繪製上的體現就是節點到節點之間會&lt;strong>有箭頭以表示方向&lt;/strong> ，對於本題來說，由於給定是無方向的，所以讀者會看到圖形上的連接僅有線條，沒有箭頭。&lt;/p>
&lt;p>接著是&lt;strong>環(cycle)&lt;/strong> ，如果一個圖可以從某個節點出發，經過&lt;strong>不重複&lt;/strong> 的節點(起點除外)，最終又能回到起始的節點，我們稱這個圖具有一個循環。&lt;/p>
&lt;p>圖的表示方式一般有兩種：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Adjacency Matrix(相鄰矩陣)，也就是如果有N個節點，就開一個NxN的矩陣Mat，當中如果A點跟B點有edge的話，Mat[A][B]=1，否則為0；可以想見，如果某個圖是無向圖的話，這個矩陣應該會沿對角線相對稱(因為Mat[A][B]會和Mat[B][A]等價)。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Adjacency List(相鄰串列)，也就是對每個節點，都用一個串列來列出跟這個節點有相連的邊的所有節點。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>一般而言，如果總體的edge數量較多的話會使用相鄰矩陣，比較少的話則會使用相鄰串列。&lt;/p>
&lt;p>其它跟圖有關的基礎其實還很多，我們容後有機會再慢慢講。&lt;/p>
&lt;p>回到我們的題目，其實它是一個相對簡單的圖，&lt;br>
因為要連接n個節點總體只需要n-1個邊，而這個圖有n個邊，&lt;br>
要讓這個圖不成環，只能將其中一個會構成環的邊給去除掉。&lt;/p>
&lt;p>那麼，我們怎麼知道哪邊會有環成立呢？&lt;br>
這邊我們可以使用union find的概念來處理。&lt;br>
union find其實是在探究&lt;strong>併查集(&lt;/strong> Disjoint-set data structure**)** 的問題。&lt;br>
用最白話的方式，就是「我們有沒有同一國」的概念。&lt;br>
什麼意思呢？&lt;/p>
&lt;p>假設一個班級有幾個小團體，這些小團體跟幫派一樣很講17且不能重覆加入，我們現在想知道究竟哪些同學屬於哪個小團體，要怎麼找呢？&lt;br>
其實很簡單，就是把每個同學叫過來問：「你的老大是誰？」&lt;/p>
&lt;p>舉例來說，如果有一個班級有兩個小團體，它們之間的層級分部是這樣的：&lt;/p>
&lt;p>A&lt;br>
| &lt;br>
B C&lt;br>
| | &lt;br>
DE- F&lt;/p>
&lt;p>G&lt;br>
|&lt;br>
H&lt;br>
|&lt;br>
I&lt;/p>
&lt;p>D會告訴你他的老大是B；&lt;br>
E會告訴你他的老大是C；&lt;br>
然後B、C會告訴你他們的老大是A；&lt;br>
最後問到A他會說：「我就是老大！」&lt;br>
於是我們就會發現B、C、D、E這四位其實都是隸屬於A的，&lt;br>
也就是他們都是同一團體的。而G、H、I則屬於另一個團體。&lt;br>
因此，我們可以對某個節點找到它最上層的節點，&lt;br>
用這個節點來定義它所屬的團體，同時在過程中依照新增的邊來合併彼此的老大，這個過程叫作&lt;strong>find&lt;/strong> 。&lt;/p>
&lt;p>那麼，我們換個角度來思考：&lt;br>
依照上面的概念，每個節點之間的邊，其實就可以代表它們是同一國的，&lt;br>
那麼，如果在看到這個邊之前，它們就已經有相同的老大了呢？&lt;br>
比如上面的圖而言，&lt;strong>對於E和F來說，由於有A-C-E跟A-C-F，&lt;br>
因此E跟F都知道自己的老大是A&lt;/strong>。&lt;br>
接著我們看到E-F的這條邊連結起來，就意味著這邊&lt;strong>構成了一個環&lt;/strong> ！&lt;br>
因為前面E已經可以連到A，F也可以連到A表示EAF之間可以連接起來，&lt;br>
因此E-F的連接就給這之間構成了一個環。&lt;/p>
&lt;p>因此，我們可以利用這點，來找出構成環的邊，就是我們要的答案了！&lt;br>
因為節點和邊的總數量我們知道是n，所有節點也只有1~n，&lt;br>
所以我們可以使用一個陣列或串列來簡單表示某個節點的老大是哪個節點。&lt;br>
如果它自己就是最大的老大的話，那麼我們就用-1來代表它沒有更上層了。&lt;/p>
&lt;p>因此，我們的解題步驟應該像這樣：&lt;/p>
&lt;ol>
&lt;li>產生一個root的陣列/串列，其長度為&lt;strong>n+1&lt;/strong> (比較方便對應1~n)，&lt;br>
其初始值均為**-1** 。&lt;/li>
&lt;li>對於edges中的每個邊edge，使用&lt;strong>find&lt;/strong> 函式找到它們的老大x跟y，&lt;br>
檢查x和y是否相同；&lt;strong>若相同，表示這個邊構成了一個環&lt;/strong> ，回傳&lt;strong>edge&lt;/strong> 即可；&lt;br>
若不同，則須統一老大，將&lt;strong>root[x]設定為y&lt;/strong> (將x這系列的上層往y這邊合併)。&lt;/li>
&lt;li>如果檢查完均檢查不到，則在外層回傳空的陣列/串列表示沒找到(但題目表示應該都會存在答案，所以理論上不會走到這邊)。&lt;/li>
&lt;/ol>
&lt;p>在&lt;strong>find函式&lt;/strong> 的定義中，輸入應該是root這個陣列跟要被確認的節點i：&lt;/p>
&lt;ol>
&lt;li>使用迴圈，當&lt;strong>root[i]不是-1時，令i = root[i]&lt;/strong> ，往上找尋更上層的老大。&lt;/li>
&lt;li>直到迴圈結束，這時候的i應該是最上層了，就&lt;strong>回傳i&lt;/strong> 即可。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部份可以使用Arrays.fill來給定一整組的陣列初始值。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/596d829af98746c03991688cfae63b09.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分則直接用*號來初始化即可，同時使用子函式，&lt;br>
略去self相關的麻煩寫法。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/718f00bd8c163db8cabb118bb6ef35ee.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(如果找尋root的時間沒有到最糟糕狀況的話為O(N)/O(N)，但我們在這個版本的只實作了find，最差狀況下find會一條線接上去，導致find的複雜度達到O(N)，這時候總體時間複雜度就會是O(N^2)。)&lt;/p>
&lt;p>「如果要實作化簡的部份的話？」&lt;br>
(化簡的概念在於將中間尋找的部分也一併處理，也就是告訴沿路上的所有節點它們最大的老大是誰，要怎麼作才能讓整個路徑更短，可以參見&lt;a class="link" href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure" target="_blank" rel="noopener"
>https://en.wikipedia.org/wiki/Disjoint-set_data_structure&lt;/a>，或者參考LeetCode的Solution也有提供，原則上是看兩個小團之間的節點數量來進行誰併到誰的決定。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 114 Stack (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-114-stack-3/</link><pubDate>Sat, 27 Feb 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-114-stack-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 114 Stack (3)" />&lt;p>&lt;strong>0946. Validate Stack Sequences (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>目前&lt;strong>0元挑戰賽&lt;/strong> 的活動已經開始囉！&lt;br>
只要&lt;strong>修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong>&lt;br>
&lt;strong>課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong>&lt;/p>
&lt;p>(目前只剩一般的套組優惠~）&lt;/p>
&lt;p>&lt;strong>零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong> &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two sequences &lt;code>pushed&lt;/code> and &lt;code>popped&lt;/code> &lt;strong>with distinct values&lt;/strong> , return &lt;code>true&lt;/code> if and only if this could have been the result of a sequence of push and pop operations on an initially empty stack.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We might do the following sequence:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>push(1), push(2), push(3), push(4), pop() -&amp;gt; 4,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>push(5), pop() -&amp;gt; 5, pop() -&amp;gt; 3, pop() -&amp;gt; 2, pop() -&amp;gt; 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: 1 cannot be popped before 2.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>0 &amp;lt;= pushed.length == popped.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= pushed[i], popped[i] &amp;lt; 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>pushed&lt;/code> is a permutation of &lt;code>popped&lt;/code>.&lt;/li>
&lt;li>&lt;code>pushed&lt;/code> and &lt;code>popped&lt;/code> have distinct values.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個序列pushed跟poped，&lt;br>
序列當中的每個值都是獨特的(也就是每個值會不同)，&lt;br>
如果對於一個空的stack進行push和pop的操作，&lt;br>
能夠完全符合pushed和poped列出來的順序的話，&lt;br>
就回傳true，否則回傳false。&lt;/p>
&lt;p>這個問題乍看之下或許有點不夠清楚，&lt;br>
簡單來說呢，就是不管如何，推入的順序一定是pushed，&lt;br>
也就是放入的時候的順序是固定的，只是選擇在什麼時候poped而已，&lt;br>
例如[1, 2, 3, 4, 5]，&lt;br>
如果我們&lt;strong>push兩次，pop一次，再push三次，pop四次&lt;/strong> ，&lt;br>
那麼我們所得到的結果會是:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>stack poped
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1, 2 　
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1, 3, 4, 5 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2, 5, 4, 3, 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>再多做一些嘗試，就會知道pop的時間點會影響到poped最終的順序結果。&lt;br>
因此，我們可以試想一下幾個情況：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>當stack裡面沒有東西 -&amp;gt; &lt;br>
沒辦法pop東西出來，必須要先push進去才行。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>當stack裡面有東西 -&amp;gt; &lt;br>
要pop出來嗎？由於每個值都相異，所以這邊出現過的數字，後面就不能出現了！因此我們應該&lt;strong>看現在poped的順序走到哪裡&lt;/strong> ，去檢查現在&lt;strong>stack最上面&lt;/strong> 是否和&lt;strong>poped對應的數字一樣&lt;/strong> ，這樣才代表需要做pop的操作。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>依照上面的想法，我們做的順序應該像這樣：&lt;/p>
&lt;ol>
&lt;li>開一個新的Stack，這邊稱為st。&lt;/li>
&lt;li>宣告一個變數i並初始化為0，用來&lt;strong>記錄下一個poped所在的index&lt;/strong> 。&lt;/li>
&lt;li>使用迴圈，依序每次從pushed取出一個num：&lt;br>
3–1. 將num推入st中&lt;br>
3–2. 當st還有值在內，且&lt;strong>最上層剛好和poped[i]相同&lt;/strong> 時，進行迴圈，&lt;br>
對st進行一次pop，並&lt;strong>遞增i&lt;/strong> (代表往下一個值來看)&lt;br>
(不相同的話，就代表這個值不該在這邊被pop出來)&lt;/li>
&lt;li>大迴圈結束後，若st剛好清空，代表這個順序是OK的，&lt;br>
&lt;strong>因此st是空的時候回傳true，否則回傳false&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，檢查stack是否為空要用isEmpty函式，&lt;br>
看stack最上層可以使用&lt;strong>peek&lt;/strong> ，也就是先偷看一下，&lt;br>
避免使用pop，因為我們還沒有篤定要將其移出stack外。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1d92e39fa0831372ed7a9fba27a039a4.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，我們可以&lt;strong>直接使用list做為stack來使用&lt;/strong> ，&lt;br>
可以使用append/pop，看最上層就直接利用&lt;strong>st[-1]&lt;/strong> 即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/24781ffdec4796128144201b8c38ef37.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，N為pushed/popped的長度)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 113 BFS (4) / Queue (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/</link><pubDate>Tue, 16 Feb 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 113 BFS (4) / Queue (5)" />&lt;p>&lt;strong>1091. Shortest Path in Binary Matrix (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>目前&lt;strong>0元挑戰賽&lt;/strong> 的活動已經開始囉！&lt;br>
只要&lt;strong>修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong>&lt;br>
&lt;strong>課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong>&lt;/p>
&lt;p>(新年優惠套組已截止囉！）&lt;/p>
&lt;p>&lt;strong>零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong> &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>In an N by N square grid, each cell is either empty (0) or blocked (1).&lt;/p>
&lt;p>A &lt;em>clear path from top-left to bottom-right&lt;/em> has length &lt;code>k&lt;/code> if and only if it is composed of cells &lt;code>C_1, C_2, ..., C_k&lt;/code> such that:&lt;/p>
&lt;ul>
&lt;li>Adjacent cells &lt;code>C_i&lt;/code> and &lt;code>C_{i+1}&lt;/code> are connected 8-directionally (ie., they are different and share an edge or corner)&lt;/li>
&lt;li>&lt;code>C_1&lt;/code> is at location &lt;code>(0, 0)&lt;/code> (ie. has value &lt;code>grid[0][0]&lt;/code>)&lt;/li>
&lt;li>&lt;code>C_k&lt;/code> is at location &lt;code>(N-1, N-1)&lt;/code> (ie. has value &lt;code>grid[N-1][N-1]&lt;/code>)&lt;/li>
&lt;li>If &lt;code>C_i&lt;/code> is located at &lt;code>(r, c)&lt;/code>, then &lt;code>grid[r][c]&lt;/code> is empty (ie. &lt;code>grid[r][c] == 0&lt;/code>).&lt;/li>
&lt;/ul>
&lt;p>Return the length of the shortest such clear path from top-left to bottom-right. If such a path does not exist, return -1.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [[0,1],[1,0]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_gvhwvqTYiqSdw4wb.png"
width="729"
height="735"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_gvhwvqTYiqSdw4wb_huf904521667f6cd35627e17a65c2ea772_10600_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_gvhwvqTYiqSdw4wb_huf904521667f6cd35627e17a65c2ea772_10600_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="99"
data-flex-basis="238px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_QarU-KLAhaaM-RzQ.png"
width="729"
height="735"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_QarU-KLAhaaM-RzQ_hu02ea2e2e43b6121fb9eae42300bdb46d_11604_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_QarU-KLAhaaM-RzQ_hu02ea2e2e43b6121fb9eae42300bdb46d_11604_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="99"
data-flex-basis="238px"
>&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [[0,0,0],[1,1,0],[1,1,0]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_fD8h6ClSM12rB3Rb.png"
width="729"
height="735"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_fD8h6ClSM12rB3Rb_hu10552abd3a8728696d1be5df5ed88c4e_14633_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_fD8h6ClSM12rB3Rb_hu10552abd3a8728696d1be5df5ed88c4e_14633_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="99"
data-flex-basis="238px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_5QjCJsJ3QAXMUYTk.png"
width="729"
height="735"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_5QjCJsJ3QAXMUYTk_hua990642157c7ff85da8e1b3a65db93c4_17852_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-113-bfs-4-queue-5/0_5QjCJsJ3QAXMUYTk_hua990642157c7ff85da8e1b3a65db93c4_17852_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="99"
data-flex-basis="238px"
>&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>1 &amp;lt;= grid.length == grid[0].length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>grid[r][c]&lt;/code> is &lt;code>0&lt;/code> or &lt;code>1&lt;/code>&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>在一個N x N的平方格子裡，每個格子可能是空的(0)，&lt;br>
不然就是阻塞住的(1)。&lt;/p>
&lt;p>一個乾淨的路徑從左上到右下的長度為k，如果路徑上的格子都是8方向(也就是九宮格的對應)相連，且開頭是(0, 0)，結尾是(N-1, N-1)，且每一格都是空的(0)。請回傳從左上到右下最短的乾淨路徑長，若不存在則回傳-1。&lt;/p>
&lt;p>這個題目其實可以有很多種不同的解決方式，&lt;br>
不過我們好久沒有使用到BFS了，就來試試看BFS的解法吧！&lt;br>
根據題目的定義，我們要找的是最短路徑，&lt;br>
所以可以從(0, 0)開始嘗試每次往8個方向各走一步，&lt;br>
並且將計數+1及標記已經走過，當在某步碰到了(N-1, N-1)時，&lt;br>
即表示我們找到了最短路徑(因為所有路線都是每次同時走一步)。&lt;br>
因此，我們需要一個Queue來記錄當前所有走到的點，&lt;br>
然後每次再將Queue的點取出，&lt;br>
找到8個方向的新的一步的點，加入到Queue中。&lt;br>
(不能超出邊界，不能已經走過，也不能被阻擋住)&lt;/p>
&lt;p>那麼我們怎麼知道同一層的要做到哪裡呢？&lt;br>
很簡單，在這層開始之前，我們先記錄下當前Queue的長度，&lt;br>
這樣子同一層只要做完這麼多個點就可以啦！&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;br>
(下面的程式碼中，我們直接把走過的路徑給標成block了，&lt;br>
這點相對較節省空間也較方便，但其實不是很正規，&lt;br>
如果面試時沒有說你可以動grid，請開出一個N x N的visited格子，&lt;br>
用來記錄有經過的點會比較好呦！)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，首先我們先檢查grid的狀況，&lt;br>
以及左上右下是否有阻擋住的狀況，有的話就直接回傳-1。&lt;br>
接著使用LinkedList作為我們的Queue，&lt;br>
可以使用add或者offer來加入新的元素。&lt;br>
當queue不為空時，每次取出一個點，往對應的8個方向取點並檢查：&lt;/p>
&lt;ol>
&lt;li>走到右下角的話代表走完，直接回傳cnt。&lt;/li>
&lt;li>如果點是合法的點的話，就將那格標記為1並加入queue中。&lt;/li>
&lt;li>每輪做完別忘記將cnt遞增。&lt;/li>
&lt;/ol>
&lt;p>全部做完還沒有碰到右下角，代表沒有解，回傳-1。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/7584199c396a39a577101b136e37b7a1.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分則使用deque來操作，&lt;br>
留意到這個題目其實也可以擴展成矩形，&lt;br>
這邊示範使用r, c的方式來記錄，但其實區別不大。&lt;br>
但對deque來說，取出記得是使用popleft，請不要誤用成pop了！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/6d86779e734b6b1610ebca1bd1fb0379.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N²)/O(N²)，最糟糕的狀況是擴散的很開的時候，&lt;br>
queue所需要的空間會很大，這個問題其實可以使用bi-directional的BFS來降低擴散的程度，可以再參考leetcode上別人的解法。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 112 Binary Search (6) / Newton’s Method</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/</link><pubDate>Mon, 01 Feb 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 112 Binary Search (6) / Newton’s Method" />&lt;p>&lt;strong>0367. Valid Perfect Square (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>目前&lt;strong>0元挑戰賽&lt;/strong> 的活動已經開始囉！&lt;br>
只要&lt;strong>修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong>&lt;br>
&lt;strong>課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong>&lt;/p>
&lt;p>&lt;strong>同時，還有限時更便宜的套組3490 (再便宜500呦！限額10名！)&lt;br>
新年限量組合🎁 零元求職挑戰賽 Python 組｜從 LeetCode 學演算法&lt;/strong>&lt;a class="link" href="https://hiskio.com/packages/ZXwe2p9yv" target="_blank" rel="noopener"
>https://hiskio.com/packages/ZXwe2p9yv&lt;/a>&lt;/p>
&lt;p>&lt;strong>零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong> &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a &lt;strong>positive&lt;/strong> integer &lt;em>num&lt;/em>, write a function which returns True if &lt;em>num&lt;/em> is a perfect square else False.&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong> ** Do not** use any built-in library function such as &lt;code>sqrt&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: num = 16
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: num = 14
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= num &amp;lt;= 2^31 - 1&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個正整數num，試檢驗num是否為完全平方數(也就是可以分解成兩個完全相等的數相乘)。&lt;br>
請不要使用內建的sqrt或類似的函式。&lt;/p>
&lt;p>雖然被封印了平方根函數，但已經看到標題的讀者應該不難猜想到，&lt;br>
我們可以運用一般的二分逼近法，&lt;br>
去將目標(我們先稱之為x)的範圍縮小。&lt;br>
當找到 x² 和num相等時，就表示num是完全平方數(回傳True)，&lt;br>
否則一路找到兩個邊界交叉時，表示num不存在整數平方根，&lt;br>
我們就可以回傳False。&lt;/p>
&lt;p>那麼，有沒有再更厲害一點的方法呢？&lt;br>
這邊來介紹一下一個著名的方法，名為牛頓法(Newton’s Method)。&lt;br>
我們在求x² = num當中的x，(下面方便起見，將num寫成n)&lt;br>
其實相當於求 y = f(x) = x² - n在y = 0時的正根。&lt;br>
假定r是這個根，我們先取一個任意一個比較大的值x0，&lt;br>
那麼它對應到的座標應該是(x0, f(x0))。&lt;br>
對於這個點做曲線的切線的話，應該可以得到切線方程式：&lt;br>
&lt;strong>y = f(x0) + f&amp;rsquo;(x0) (x-x0) &lt;br>
也就是y = ax +b嘛! a就是在x0上的切線斜率，&lt;br>
而x代入x0的話可以驗證y = f(x0)，&lt;br>
所以這個方程式可以表達該切線沒錯。&lt;/strong>&lt;/p>
&lt;p>我們將這個切線叫做L，&lt;br>
那麼L和x軸的交點的x座標，應該就和r更近囉！&lt;br>
(想像一下拋物線的斜度會越來越平，所以切線和x軸的交點，&lt;br>
比起拋物線和x軸的交點來說應該會大一點)&lt;br>
我們將後面和x軸的交點位置叫做&lt;strong>x1&lt;/strong> ，&lt;br>
那麼就可以計算其&lt;strong>斜率為 f(x0) / (x0-x1) = (x0²-n)/(x0-x1)&lt;/strong> ，&lt;br>
同時也等於&lt;strong>f(x)的導數(就是對其微分)f’(x) = 2x&lt;/strong> 。&lt;br>
因此，2x0 = (x0²-n)/(x0-x1) -&amp;gt; 2x0(x0-x1) = x0²-n&lt;br>
繼續化簡：&lt;br>
-&amp;gt; 2x0²-2x0x1=x0²-n&lt;br>
-&amp;gt; x0²+n = 2x0x1&lt;br>
-&amp;gt; &lt;strong>x1 = (x0 + n/x0) / 2&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001.png"
width="800"
height="734"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001_huac58c9f2d8f76819827b64963d18fa89_173391_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001_huac58c9f2d8f76819827b64963d18fa89_173391_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="108"
data-flex-basis="261px"
>&lt;/p>
&lt;p>每次取得一個更接近的x來逼近r的位置&lt;/p>
&lt;p>我們可以再用這個x1再取得在f(x)上的點，接下來再畫切線，&lt;br>
重復上面的動作。&lt;br>
當我們每次用前面這個算式迭代，就可以取得一個新的x，&lt;br>
理論上它會更接近於r。(x1, x2, x3, …)&lt;br>
由於要取的是整數，所以我們在計算的時候，&lt;br>
就將所有的算式中的除法都取整數，&lt;br>
這樣算出來的狀況，就會變得有機會更小。&lt;br>
所以在運用到實際的計算時，&lt;br>
我們可以設定一個迴圈，將x直接先定為num，&lt;br>
當x² &amp;gt; num時，就持續迴圈，&lt;br>
那麼在x持續縮小的狀況下，&lt;br>
最終要嘛縮小到剛好得到一個正整數的平方根，&lt;br>
要嘛就是x²已經小於num了，我們就不用繼續往下做啦！&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java-java的部分請留意到大小問題我們應該要使用long來宣告變數">Java Java的部分，請留意到大小問題，我們應該要使用long來宣告變數。
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/22935065681018fa2120af827ebe5788.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python部分則請不要忘記整數除法是”//”。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/a9273b962c9c694532f561c075e4a097.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(時間複雜度難以界定，最差應該是O(num)，(但二分法也是)&lt;br>
平均應該優於O(log(num))，這可能也取決於初始值的取法；&lt;br>
空間複雜度則為O(1))&lt;/p>
&lt;p>&lt;strong>相似及延伸：&lt;br>
本題還有其他的解法可以參考以下連結&lt;/strong>&lt;a class="link" href="https://leetcode.com/problems/valid-perfect-square/discuss/130010/Python-4-Methods-with-time-testing" target="_blank" rel="noopener"
>https://leetcode.com/problems/valid-perfect-square/discuss/130010/Python-4-Methods-with-time-testing&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 111 DFS (18) / Backtracking (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-111-dfs-18-backtracking-8/</link><pubDate>Wed, 20 Jan 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-111-dfs-18-backtracking-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 111 DFS (18) / Backtracking (8)" />&lt;p>&lt;strong>0784. Letter Case Permutation (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>目前&lt;strong>0元挑戰賽&lt;/strong> 的活動已經開始囉！&lt;br>
只要&lt;strong>修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong>&lt;br>
&lt;strong>課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong>&lt;/p>
&lt;p>&lt;strong>零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong> &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string.&lt;/p>
&lt;p>Return &lt;em>a list of all possible strings we could create&lt;/em>. You can return the output in &lt;strong>any order&lt;/strong> .&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: S = &amp;#34;a1b2&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;a1b2&amp;#34;,&amp;#34;a1B2&amp;#34;,&amp;#34;A1b2&amp;#34;,&amp;#34;A1B2&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: S = &amp;#34;3z4&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;3z4&amp;#34;,&amp;#34;3Z4&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: S = &amp;#34;12345&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;12345&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: S = &amp;#34;0&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;0&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>S&lt;/code> will be a string with length between &lt;code>1&lt;/code> and &lt;code>12&lt;/code>.&lt;/li>
&lt;li>&lt;code>S&lt;/code> will consist only of letters or digits.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串S，&lt;br>
我們可以任意將其中的單一字母轉換成小寫或大寫，&lt;br>
以創造出另一個字串。&lt;br>
回傳一個列表，當中包含所有我們可以創造出來的字串。&lt;br>
(回傳的字串順序可以不同)&lt;br>
(限制：S的長度會在1~12之間，且S只會有字母或數字)&lt;/p>
&lt;p>這個題目實際上並不是很難想，&lt;br>
從直觀上來說，就是找出所有字母的地方(因為只有字母可以變)，&lt;br>
讓它是小寫或大寫這兩種可能，會產生不一樣的字串，&lt;br>
因此如果當中存在L個字母的話，&lt;br>
其變化就會有2^L種。&lt;/p>
&lt;p>那麼，我們怎麼樣處理這樣子的產生的過程呢？&lt;br>
這就要回頭複習一下回溯法的概念了！&lt;br>
以前我們提到過，回溯法就是當走到一段，無法再往下走時，&lt;br>
回到上一步並還原前面的痕跡，再往下一條路走的做法。&lt;br>
因此，我們來看待這題會變成這樣：&lt;/p>
&lt;ol>
&lt;li>先將整個字串&lt;strong>轉成小寫&lt;/strong> (要都轉成大寫也可以)&lt;/li>
&lt;li>從&lt;strong>index 0&lt;/strong> 開始往下走(將現在的位置定為&lt;strong>pos&lt;/strong> )，&lt;br>
當順著往下走&lt;strong>都不改變&lt;/strong> 時，&lt;br>
最後應該會走到底部，此時&lt;strong>pos == 整個字串長&lt;/strong> ，&lt;br>
這會是&lt;strong>其中一個字串變化，可記錄到結果(res)中&lt;/strong> 。&lt;/li>
&lt;li>接著，回到上一步時，&lt;br>
我們可以&lt;strong>檢查pos位置是否為字母&lt;/strong> ，&lt;br>
&lt;strong>是的話&lt;/strong> ，我們可以&lt;strong>改成將該位置的字母轉為大寫&lt;/strong> ，&lt;br>
再重新往下走一次(因為這樣子變化又不一樣了)&lt;/li>
&lt;li>走到底回到上一層時，&lt;strong>再將字母轉回小寫(回溯法的復原)&lt;/strong>&lt;/li>
&lt;li>最終，全數走完時，&lt;strong>res&lt;/strong> 即會紀錄所有的答案。&lt;/li>
&lt;/ol>
&lt;p>所以在使用DFS和回溯法時，&lt;br>
讀者請切記兩個要點：&lt;br>
&lt;strong>1. 走到死路(結束時該回頭)的條件要設定好&lt;br>
2. 被更改的東西，在這條路線結束後，記得復原&lt;/strong>&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，使用toLowerCase()和toCharArray()，&lt;br>
將字串轉換成&lt;strong>全小寫&lt;/strong> 的字元陣列，方便修改；&lt;br>
我們用helper函數來進行DFS+Backtracking。&lt;br>
在轉換上，使用new String(a)可以從一個字元陣列生成一個字串。&lt;br>
可能&lt;/p>
&lt;script src="https://gist.github.com/Desolve/a96c8a3c9e1c3ffd013e148d9d61da53.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，使用&lt;strong>list()&lt;/strong> 來拆成串列，&lt;br>
同時組成字串是使用**’’.join()** 來處理的，&lt;br>
檢查字母是使用&lt;strong>isalpha()&lt;/strong> 函式；&lt;br>
同時請留意**.upper()和.lower()並不直接對原來的東西做修改** ，&lt;br>
而是會&lt;strong>回傳新的str&lt;/strong> ，所以請將其輸入回a[pos]裡，&lt;br>
才會真正修改到。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1d4f551f6da272348a1edad6d6a61c26.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(2^L)/O(len(S)), L為字串中字母的數量)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 110 Array (16) / Greedy Algorithm (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-110-array-16-greedy-algorithm-1/</link><pubDate>Sun, 17 Jan 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-110-array-16-greedy-algorithm-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 110 Array (16) / Greedy Algorithm (1)" />&lt;p>&lt;strong>0881. Boats to Save People (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>目前&lt;strong>0元挑戰賽&lt;/strong> 的活動已經開始囉！&lt;br>
只要&lt;strong>修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong>&lt;br>
&lt;strong>課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong>&lt;/p>
&lt;p>&lt;strong>零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong> &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
>http://bit.ly/zeroclg&lt;/a>&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>The &lt;code>i&lt;/code>-th person has weight &lt;code>people[i]&lt;/code>, and each boat can carry a maximum weight of &lt;code>limit&lt;/code>.&lt;/p>
&lt;p>Each boat carries at most 2 people at the same time, provided the sum of the weight of those people is at most &lt;code>limit&lt;/code>.&lt;/p>
&lt;p>Return the minimum number of boats to carry every given person. (It is guaranteed each person can be carried by a boat.)&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: people = [1,2], limit = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: 1 boat (1, 2)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: people = [3,2,2,1], limit = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: 3 boats (1, 2), (2) and (3)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: people = [3,5,3,4], limit = 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: 4 boats (3), (3), (4), (5)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note&lt;/strong> :&lt;/p>
&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= people.length &amp;lt;= 50000&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= people[i] &amp;lt;= limit &amp;lt;= 30000&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>有一群人people，當中第i個人的重量是people[i]，&lt;br>
且每艘船最重可以載重limit，同時最多只能乘載2個人，&lt;br>
乘載的重量最多為limit(剛好的話也可以)&lt;br>
試計算並回傳最少所需裝載所有人的船的數量。&lt;/p>
&lt;p>乍看之下，這題是不是有點像以前的Two Sum?&lt;br>
但再仔細想想，就會發現，&lt;br>
由於我們並不一定要每艘船都裝載到limit的重量，&lt;br>
所以並不能夠形成相加等於特定和的關係。&lt;/p>
&lt;p>那麼該怎麼處理呢？&lt;br>
如果這群人是由小到大排列的話，&lt;br>
不管如何最重的那些人都還是要上船，&lt;br>
所以我們先挑最右邊的(最重的人)上船。&lt;br>
接下來這艘船還能不能帶人呢？&lt;br>
我們就再幫忙找最左邊的(最輕的人)看能不能湊一組，&lt;br>
可以湊就沒問題，不能湊也無法強求，就只好讓這個人自己一條船囉！&lt;br>
這樣搭配下，我們就可以盡可能先幫較重的人找看看能不能組起來，&lt;br>
因此會是所需求的船隻數量會是最小的。&lt;/p>
&lt;p>上面這樣子的概念，被稱為&lt;strong>貪婪演算法(Greedy Algorithm)&lt;/strong> 。&lt;br>
貪婪演算法的核心精神，在於先找到一個方法，&lt;br>
使得每次盡可能都處理所有可以操作的單位，&lt;br>
再依序往下做處理，這樣的方法是&lt;strong>對總體來說也是最佳&lt;/strong> 的時候，&lt;br>
就符合貪婪演算法的特性。&lt;br>
請讀者務必留意，&lt;br>
如果像是&lt;strong>動態規劃(Dynamic Programming)&lt;/strong> 這類型的問題，&lt;br>
就顯然&lt;strong>不會符合&lt;/strong> 貪婪演算法的作法，&lt;br>
因為&lt;strong>局部的最佳解，不見得會是全局的最佳解&lt;/strong> 。&lt;/p>
&lt;p>所以對這題來說，當我們排序完這群人以後，&lt;br>
從最重的開始盡可能幫其安排組合，對總體來說就會是最好的。&lt;/p>
&lt;p>因此，我們的大體解法應該如下：&lt;/p>
&lt;ol>
&lt;li>先將people由小到大排序&lt;/li>
&lt;li>令&lt;strong>l = 0, r = people.length - 1, res = 0 (用來記錄需要幾艘船)&lt;/strong>&lt;/li>
&lt;li>使用一個迴圈，當 &lt;strong>l ≤ r&lt;/strong> 時，進行以下操作：&lt;br>
3–1. 如果 &lt;strong>people[l]+people[r]&amp;lt;= limit&lt;/strong> 時，&lt;br>
代表可以捎上&lt;strong>index l&lt;/strong> 的人，此時將** l&lt;strong>遞增。&lt;br>
3–2. 由於&lt;/strong>所有人的重量都一定小於limit** ，(題目說的)&lt;br>
所以&lt;strong>people[r]一定可以占一艘船&lt;/strong> (不管people[l]有沒有上船)，&lt;br>
所以我們將&lt;strong>r遞減&lt;/strong> ，並且將&lt;strong>res遞增&lt;/strong> ，這艘船我們就處理完囉！&lt;/li>
&lt;li>&lt;strong>回傳res&lt;/strong> 即為答案。&lt;/li>
&lt;/ol>
&lt;p>讀者可能會問：咦？那&lt;strong>l和r重疊&lt;/strong> 的話怎麼辦？&lt;br>
問得好！重疊的話，由於不論怎麼樣r都會遞減，&lt;br>
所以重疊的時候，事實上就是相&lt;strong>當於3–1沒有任何作用&lt;/strong> ，&lt;br>
但並沒有影響到我們要計算的res，對吧XD？&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的話使用Arrays.sort()，&lt;br>
其他部分應該相當直觀。&lt;br>
這裡提供LeetCode的另一種解法，&lt;br>
由於有limit的限制，所以我們可以利用長度為limit+1的陣列，&lt;br>
來達到排序的效果(這相當於O(limit)的空間去換取時間複雜度降低)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/c17604819bd171671e5a4a3cd1dc299c.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的排序則直接對串列進行.sort()即可，&lt;br>
讀者請記得sorted()函式是產生一個新的排序的串列，別搞混喲！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/c315324b270acabd8a584d6b8554adf8.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(NlogN)/O(1)，N為people的長度。&lt;br>
如果是使用Java附上的參考解的話則是O(limit)/O(limit))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 109 Array (15) / Hash Table (11)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-109-array-15-hash-table-11/</link><pubDate>Fri, 08 Jan 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-109-array-15-hash-table-11/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 109 Array (15) / Hash Table (11)" />&lt;p>&lt;strong>1640. Check Array Formation Through Concatenation (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>好久不見！筆者最近剛換了工作，&lt;br>
所以比較忙一點XD &lt;strong>之後1月中會有HiSKIO 技術年貨節的活動，&lt;br>
歡迎大家拿著折價券來修從LeetCode學演算法的課程喲！&lt;br>
如果預算不夠，相信這108篇也還是很夠讀者練習的啦XDD&lt;/strong>&lt;/p>
&lt;p>在更之後還有規劃0元挑戰賽的部分，&lt;br>
只要&lt;strong>修課後一定時間內成功錄取新工作&lt;/strong> ，&lt;br>
&lt;strong>課程就會全額退費喲！&lt;/strong> 這部分再請留意官方那邊的公告，&lt;br>
如果有開始的話，文章中也會再提醒各位。&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are given an array of &lt;strong>distinct&lt;/strong> integers &lt;code>arr&lt;/code> and an array of integer arrays &lt;code>pieces&lt;/code>, where the integers in &lt;code>pieces&lt;/code> are ** distinct**. Your goal is to form &lt;code>arr&lt;/code> by concatenating the arrays in &lt;code>pieces&lt;/code> ** in any order**. However, you are ** not** allowed to reorder the integers in each array &lt;code>pieces[i]&lt;/code>.&lt;/p>
&lt;p>Return &lt;code>true&lt;/code> &lt;em>if it is possible to form the array&lt;/em> &lt;code>arr&lt;/code> &lt;em>from&lt;/em> &lt;code>pieces&lt;/code>. Otherwise, return &lt;code>false&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [85], pieces = [[85]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [15,88], pieces = [[88],[15]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Concatenate [15] then [88]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [49,18,16], pieces = [[16,18,49]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Even though the numbers match, we cannot reorder pieces[0].
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Concatenate [91] then [4,64] then [78]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-5">Example 5
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [1,3,5,7], pieces = [[2,4,6,8]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= pieces.length &amp;lt;= arr.length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>sum(pieces[i].length) == arr.length&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= pieces[i].length &amp;lt;= arr.length&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= arr[i], pieces[i][j] &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>The integers in &lt;code>arr&lt;/code> are &lt;strong>distinct&lt;/strong> .&lt;/li>
&lt;li>The integers in &lt;code>pieces&lt;/code> are &lt;strong>distinct&lt;/strong> (i.e., If we flatten pieces in a 1D array, all the integers in this array are distinct).&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個陣列arr，當中有不同的整數們，&lt;br>
以及另一個整數陣列的陣列pieces(好饒口XD)，&lt;br>
當中所有的pieces中的整數也都是相異的，&lt;br>
我們的目標就是要將pieces拼接成arr，&lt;br>
但pieces中要怎麼接順序都沒關係，&lt;br>
&lt;strong>但每一個pieces中的子陣列中的順序不可以被調換&lt;/strong> 。&lt;br>
(例如arr = [15,88], pieces = [[88],[15]]，&lt;br>
可以先拚[15]再拚[88]從而組出arr，可回傳true；&lt;br>
但arr = [49,18,16], pieces = [[16,18,49]]的話，&lt;br>
因為[16,18,49]內不能夠調換順序，所以只能回傳false)&lt;/p>
&lt;p>如果拚得起來就回傳true，否則回傳false。&lt;/p>
&lt;p>條件限制：&lt;/p>
&lt;ol>
&lt;li>arr的長度和pieces的長度均為1~100之間(後者小於前者)。&lt;/li>
&lt;li>pieces的所有子陣列長度總和，和arr陣列長度相等。&lt;/li>
&lt;li>arr和pieces的所有子陣列中的元素值均在1~100之間。&lt;/li>
&lt;li>arr中的所有整數均為相異。&lt;/li>
&lt;li>pieces中的所有整數均為相異。&lt;/li>
&lt;/ol>
&lt;p>根據條件限制的部分，我們可以簡單得到，&lt;br>
反正要能對上的話，因為總個數剛好相等，&lt;br>
所以&lt;strong>不存在第二種對應方式&lt;/strong> ！&lt;br>
既然不存在第二種對應的方式，&lt;br>
那麼我們在arr中看到一個開頭時，&lt;br>
我們應該只要&lt;strong>在pieces中找那個值&lt;/strong> ，&lt;br>
就知道該對上pieces中的那一個子陣列囉！&lt;/p>
&lt;p>那麼，我們該怎麼樣去找對應呢？&lt;br>
每次都掃過一輪去找，時間複雜度感覺會很糟糕，&lt;br>
那麼，想要迅速的找到對應的位置，&lt;br>
我們就會想到利用HashTable的概念。&lt;br>
因此，在Java使用HashMap，Python中則使用dictionary，&lt;br>
就可以讓我們使用O(1)的複雜度進行存取(不過前面要先花O(N)來存喲！)&lt;/p>
&lt;p>這邊我們可以選擇將每個(pieces[i][0], i)的對應存入，&lt;br>
這樣在搜尋時，我們就知道接下來要拚入哪一組子陣列囉！&lt;/p>
&lt;p>接著我們需要遍歷整個arr，&lt;br>
每次先拿第一個值去搜尋到對應的pieces，&lt;br>
接著依序一個一個去對照兩邊的值是否相等。&lt;br>
如果找不到對應或者是值不相等，就表示無法對應成功囉！&lt;br>
(可以直接回傳false)&lt;br>
如果全數拚完都沒問題，自然就可以回傳true。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java-java的部分我們使用hashmap來記錄">Java Java的部分，我們使用HashMap來記錄，
&lt;/h3>&lt;p>記得使用&lt;strong>put(key, value)&lt;/strong> 的形式！&lt;br>
(因為沒有重複的問題，所以也不需要檢查)&lt;/p>
&lt;p>接著我們利用cnt來進行遍歷的紀錄，&lt;br>
這邊&lt;strong>不要忘記先檢查&lt;/strong> 能不能找到arr[cnt]啊！&lt;br>
(因為有可能找不到，直接用get會有exception的！)&lt;br>
另外，由於get出來是Integer，&lt;br>
這邊我們&lt;strong>使用(int)來將其轉型回一般的int&lt;/strong> 。&lt;br>
其他就依序處理即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/05f2cd5f34d32264fdc74ae1dac90d65.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，字典和list的操作方式差不多，&lt;br>
不過還是不要忘記先檢查喲！&lt;br>
另外對初學的讀者提醒一下，&lt;br>
&lt;strong>Python中沒有++或&amp;ndash;這種方便的遞增/遞減方式&lt;/strong> ，&lt;br>
所以請乖乖使用&lt;strong>cnt += 1或cnt = cnt + 1&lt;/strong> 。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/d7ca363defdd266301bc5f37e956e7d4.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(pieces的子陣列個數，最大為N))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 108 Tree (20) / DFS (17)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/</link><pubDate>Sun, 03 Jan 2021 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 108 Tree (20) / DFS (17)" />&lt;p>&lt;strong>1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>好久不見！筆者最近剛換了工作，&lt;br>
所以比較忙一點XD &lt;strong>之後1月中會有HiSKIO 技術年貨節的活動，&lt;br>
歡迎大家拿著折價券來修從LeetCode學演算法的課程喲！&lt;br>
如果預算不夠，相信這108篇也還是很夠讀者練習的啦XDD&lt;/strong>&lt;/p>
&lt;p>在更之後還有規劃0元挑戰賽的部分，&lt;br>
只要&lt;strong>修課後一定時間內成功錄取新工作&lt;/strong> ，&lt;br>
&lt;strong>課程就會全額退費喲！&lt;/strong> 這部分再請留意官方那邊的公告，&lt;br>
如果有開始的話，文章中也會再提醒各位。&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two binary trees &lt;code>original&lt;/code> and &lt;code>cloned&lt;/code> and given a reference to a node &lt;code>target&lt;/code> in the original tree.&lt;/p>
&lt;p>The &lt;code>cloned&lt;/code> tree is a &lt;strong>copy of&lt;/strong> the &lt;code>original&lt;/code> tree.&lt;/p>
&lt;p>Return &lt;em>a reference to the same node&lt;/em> in the &lt;code>cloned&lt;/code> tree.&lt;/p>
&lt;p>&lt;strong>Note&lt;/strong> that you are ** not allowed** to change any of the two trees or the &lt;code>target&lt;/code> node and the answer ** must be** a reference to a node in the &lt;code>cloned&lt;/code> tree.&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong> Solve the problem if repeated values on the tree are allowed.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM.png"
width="544"
height="426"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM_hu3c414c453ee8a0776ed82fa5ba53c513_23530_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_GYOQ1UwiPY_qi4UM_hu3c414c453ee8a0776ed82fa5ba53c513_23530_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="127"
data-flex-basis="306px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: tree = [7,4,3,null,null,6,19], target = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK.png"
width="221"
height="159"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK_hub6c39a0d6263de9e097ce185b881689b_4878_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_8XmwUepRVQFlWNjK_hub6c39a0d6263de9e097ce185b881689b_4878_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="138"
data-flex-basis="333px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: tree = [7], target = 7
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq.png"
width="459"
height="486"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq_hu666b47b8013542057d996d90693ec9ae_19071_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_K4tA1xRKWOkLeMBq_hu666b47b8013542057d996d90693ec9ae_19071_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="94"
data-flex-basis="226px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: tree = [8,null,6,null,5,null,4,null,3,null,2,null,1], target = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel.png"
width="800"
height="344"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel_hu77a1921c26f1a7b6cdedf7b4aa42816b_54351_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_fRlfsY4PDxTsuWel_hu77a1921c26f1a7b6cdedf7b4aa42816b_54351_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="232"
data-flex-basis="558px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: tree = [1,2,3,4,5,6,7,8,9,10], target = 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-5">Example 5
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2.png"
width="427"
height="345"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2_hu26259bcab327176ec3a671c5bbcff196_13831_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-108-tree-20-dfs-17/0_2F34zOAHfHFDUEu2_hu26259bcab327176ec3a671c5bbcff196_13831_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="123"
data-flex-basis="297px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: tree = [1,2,null,3], target = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>The number of nodes in the &lt;code>tree&lt;/code> is in the range &lt;code>[1, 10^4]&lt;/code>.&lt;/li>
&lt;li>The values of the nodes of the &lt;code>tree&lt;/code> are unique.&lt;/li>
&lt;li>&lt;code>target&lt;/code> node is a node from the &lt;code>original&lt;/code> tree and is not &lt;code>null&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個二元樹 original 跟 cloned ，&lt;br>
並給定一個 originl 樹上的參考節點 target，&lt;br>
當中，cloned是original的完全複製，&lt;br>
請找到 cloned 上和 target 相對應的相同節點回傳。&lt;br>
留意兩棵樹上的節點都不允許被改變，&lt;br>
且答案必須要是cloned這棵樹上的對應節點。&lt;br>
(而不是original上的或新作出來的節點)&lt;/p>
&lt;p>條件限制：&lt;/p>
&lt;ol>
&lt;li>樹上的總節點數量範圍在1到10⁴之間。&lt;/li>
&lt;li>樹上的各節點值均為&lt;strong>獨一無二&lt;/strong> 的。&lt;/li>
&lt;li>target是original這棵樹上的節點，且不為null。&lt;/li>
&lt;/ol>
&lt;p>後續：如果重複值可被允許，嘗試在這個條件下解決問題。&lt;/p>
&lt;p>這題雖然標為Medium，但說實在的不難XD&lt;br>
看完題目以後，已經經歷過前面各種難題的讀者，&lt;br>
應該會直覺想到使用DFS來解決。&lt;/p>
&lt;p>那麼，由於題目一開始已經給定說值是全部獨一無二。&lt;br>
如果先不計較Follow up的部分，&lt;br>
其實我們可以直接比較值就可以了！&lt;br>
我們可以直接將target的值當作目標，&lt;br>
並且對於cloned這棵樹進行dfs，只要比較到相同的值，&lt;br>
就可以進行回傳啦！&lt;br>
由於1的關係，我們不用擔心使用遞迴會超過call stack限制，&lt;br>
使用一個helper函式，當遇到null/None時，&lt;br>
回傳null/None，接著&lt;strong>檢查所在節點值是否和target的值相同&lt;/strong> ；&lt;br>
接著分別&lt;strong>dfs往左邊和往右邊的樹進行尋找&lt;/strong> 。&lt;/p>
&lt;p>當&lt;strong>左邊已經找到時，我們可以不用再檢查右邊的部分&lt;/strong> ，&lt;br>
直接回傳得到的節點；否則&lt;strong>當右邊有找到時，回傳右邊得到的節點&lt;/strong> ；&lt;br>
&lt;strong>當右邊也沒有找到時，則回傳null/None&lt;/strong> 。&lt;/p>
&lt;p>那麼，如果節點值不一定獨一無二呢？&lt;br>
那麼我們就要同時也將original一起進行遞迴，&lt;br>
這時候檢查的就是original上歷經的節點是否是target節點，&lt;br>
在檢查到的時候同時去回傳cloned的對應節點。&lt;/p>
&lt;p>這時候我們&lt;strong>用來檢查相等的就是記憶體位址，而非節點值&lt;/strong> 。&lt;br>
因為唯有記憶體位址相同時，能保證這個節點是對應位置的那個節點。&lt;br>
(而非只有裡面的值相同)&lt;/p>
&lt;p>依此，我們寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分我們額外提供了LeetCode上Follow Up的解法在註解，&lt;br>
使用相同的做法，應該也可以寫出Python的方法，&lt;br>
讀者可以自行嘗試看看。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/af0e4cf14db21baf15da0e10aa9b4121.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，請讀者留意，&lt;br>
對Python而言，我們寫n: TreeNode, v: int這樣的格式，&lt;br>
是&lt;strong>寫給人看的&lt;/strong> XD，讀者也可以完全都不寫，一樣可以執行。&lt;br>
而且對於使用者來說，就算你將v代成不是int的東西，&lt;br>
也不會直接被Python視為錯誤，&lt;br>
並不像Java或其他程式語言那樣對這邊有型別檢查，&lt;br>
這點請務必留意喲！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/dd29c995eb91cf5776d22c618eed221d.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，基本上最差的狀況要遍歷整棵樹，&lt;br>
而空間上要計較Call Stack的話，則會跟樹的深度成正比，&lt;br>
除此以外沒有其他額外和N相關的部分)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 107 String (7) / Stack (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-107-string-7-stack-2/</link><pubDate>Sat, 12 Dec 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-107-string-7-stack-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 107 String (7) / Stack (2)" />&lt;p>&lt;strong>1544. Make The String Great (Easy)&lt;/strong>&lt;/p>
&lt;p>好久不見啦！最近筆者比較忙碌，還請多多見諒XD&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string &lt;code>s&lt;/code> of lower and upper case English letters.&lt;/p>
&lt;p>A good string is a string which doesn’t have &lt;strong>two adjacent characters&lt;/strong> &lt;code>s[i]&lt;/code> and &lt;code>s[i + 1]&lt;/code> where:&lt;/p>
&lt;ul>
&lt;li>&lt;code>0 &amp;lt;= i &amp;lt;= s.length - 2&lt;/code>&lt;/li>
&lt;li>&lt;code>s[i]&lt;/code> is a lower-case letter and &lt;code>s[i + 1]&lt;/code> is the same letter but in upper-case or &lt;strong>vice-versa&lt;/strong> .&lt;/li>
&lt;/ul>
&lt;p>To make the string good, you can choose &lt;strong>two adjacent&lt;/strong> characters that make the string bad and remove them. You can keep doing this until the string becomes good.&lt;/p>
&lt;p>Return &lt;em>the string&lt;/em> after making it good. The answer is guaranteed to be unique under the given constraints.&lt;/p>
&lt;p>&lt;strong>Notice&lt;/strong> that an empty string is also good.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;leEeetcode&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;leetcode&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: In the first step, either you choose i = 1 or i = 2, both will result &amp;#34;leEeetcode&amp;#34; to be reduced to &amp;#34;leetcode&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;abBAcC&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We have many possible scenarios, and all lead to the same answer. For example:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#34;abBAcC&amp;#34; --&amp;gt; &amp;#34;aAcC&amp;#34; --&amp;gt; &amp;#34;cC&amp;#34; --&amp;gt; &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#34;abBAcC&amp;#34; --&amp;gt; &amp;#34;abBA&amp;#34; --&amp;gt; &amp;#34;aA&amp;#34; --&amp;gt; &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;s&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;s&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= s.length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>s&lt;/code> contains only lower and upper case English letters.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串s，當中含有大小寫的英文字母，&lt;br>
一個好的字串被定義為對於 &lt;strong>0 ≤ i ≤ s.length - 2&lt;/strong> 來說，&lt;br>
兩個相鄰的字元s[i]和s[i+1]不會含有相同字母但大小寫相反的狀況，&lt;br>
例如aA, Cc這種型式。&lt;/p>
&lt;p>要讓字串變好，可以透過每次拿掉兩個相鄰且讓字串變壞的字元達到，&lt;br>
最終得到一個好的字串。&lt;/p>
&lt;p>題目表示給定的題目一定有答案且必然是唯一的。&lt;br>
(空字串也是好的字串)&lt;/p>
&lt;p>說起來這題的標題不禁讓人想到美國總統大選，&lt;br>
不過到現在恐怕已經大勢底定了就是，&lt;br>
這句話恐怕就要成為絕響了吧XD&lt;/p>
&lt;p>扯遠了，我們來看看這題。&lt;/p>
&lt;p>由於它已經保證會有唯一解，&lt;br>
那麼相鄰字元的移除順序理論上並不會影響結果，&lt;br>
所以直觀上好像可以每次掃過一遍字串，&lt;br>
將大小寫相鄰的相同字母移掉就解決了&amp;hellip;&amp;hellip;嗎？&lt;/p>
&lt;p>但這麼做的話，我們會不知道要掃過幾次字串才能夠將所有問題移除完，&lt;br>
因為比如碰到&lt;strong>abBA&lt;/strong> 這樣子的字串，我們要將**’bB’** 移除掉，&lt;br>
才會在下一次發現**’aA’** 可以移除。&lt;/p>
&lt;p>所以為求簡單起見，&lt;br>
我們可以使用一個&lt;strong>Stack&lt;/strong> 來存放已經檢查過的部分，&lt;br>
每次放一個字元到Stack中，存放前將Stack最上面的那個字元，&lt;br>
跟準備要放的字元做比較：&lt;br>
&lt;strong>兩者是相同字母且大小寫相反-&amp;gt;將Stack中最上面的字元pop掉&lt;br>
兩者不需相消-&amp;gt;放入Stack&lt;/strong>&lt;/p>
&lt;p>這麼一來，我們就只會放沒有讓字串變壞的字元進到Stack，&lt;br>
同時每次都會拿新的字元跟前面的比對，以排除掉應該移除的部分。&lt;/p>
&lt;p>那麼，怎麼算大小寫相反呢？&lt;br>
除了用upper/lower case相關的函式外，&lt;br>
&lt;strong>在&lt;/strong> &lt;a class="link" href="https://zh.wikipedia.org/wiki/ASCII" target="_blank" rel="noopener"
>&lt;strong>ASCII Code&lt;/strong> &lt;/a>&lt;strong>中，相同大小寫的字母的對應碼會恰巧差32。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>為什麼不是26? 因為中間還有帶一些標點符號。&lt;/strong> Python中我們可以使用ord()來對一個字元取其ASCII Code值，&lt;br>
而在Java中，我們可以視char為一個數字來進行加減運算，&lt;br>
所以直接相加減就可以了。&lt;/p>
&lt;p>可能有讀者會問：&lt;br>
&lt;strong>「那我記不住32這個數字怎麼辦？」&lt;/strong>&lt;/p>
&lt;p>在寫的過程中，我們也可以用’a’和’A’的位置差算出來，&lt;br>
注意**’a’對應的值是比較大** 的呦！&lt;br>
所以可以將其寫成：&lt;strong>&amp;lsquo;a&amp;rsquo; - &amp;lsquo;A&amp;rsquo; (Java)或 ord(‘a’)- ord(‘A’) (Python)&lt;/strong>&lt;/p>
&lt;p>你再問：&lt;br>
&lt;strong>「那我記不住哪個在前面怎麼辦？」&lt;/strong>&lt;br>
呃……那你只好再&lt;strong>加個絕對值&lt;/strong> 了！&lt;br>
使用Math.abs() (Java) 或 abs() (Python)就可以囉！&lt;/p>
&lt;p>因此，流程大體如下：&lt;/p>
&lt;ol>
&lt;li>建立一個stack名為st&lt;/li>
&lt;li>從字串s當中依序取出字元c，進行迴圈：&lt;br>
2-1. 當st不為空，且最上面的值和c的值&lt;strong>相差32&lt;/strong> 時，就對st進行pop&lt;br>
2-2. 否則表示不需消除，將c推入st中(push)&lt;/li>
&lt;li>完成迴圈後，將st的所有字元連起來得到的字串即為答案&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，由於Java的Stack固定從尾端取出，&lt;br>
最終使用StringBuilder進行組合完以後，toString之前記得要reverse，&lt;br>
不然答案就會反掉囉XD！&lt;br>
當然，也可以採用ArrayDeque來做，&lt;br>
這樣就可以從頭排列到尾而不需要反轉。&lt;br>
使用peek()可以幫助我們確認stack的最上面一個值是什麼，&lt;br>
而不會將其取出，同時因不確定大小寫誰在前面，&lt;br>
所以檢查時要記得取絕對值！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/3c225e5679bc20afbbef6839ca86f140.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python這邊多加了一條判斷，但其實不影響，&lt;br>
只是s的長度是1或0時都可以直接回傳就是了XD&lt;/p>
&lt;p>我們可以看到對於Python來說好處就是可以直接拿list當stack來使用，&lt;br>
同時，使用join函式可以簡單地將list組成字串。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/f7e2c4a352a01676f7dde17345c9f762.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，N為字串長度。Java也可以使用CharAt(i)的型式來處理取出字元的部分，但不影響空間複雜度，因為後面還有其他要組的部分XD)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>想看看其他題目嗎？&lt;br>
歡迎從&lt;a class="link" href="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/" >&lt;strong>第零篇&lt;/strong> &lt;/a>找你想要的！&lt;/p>
&lt;p>同時追蹤粉專以獲得更多新文章的通知：&lt;br>
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
>&lt;strong>跟著Desolve學程式&lt;/strong> &lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 106 Tree (19) / DFS (16)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/</link><pubDate>Mon, 09 Nov 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 106 Tree (19) / DFS (16)" />&lt;p>&lt;strong>0563. Binary Tree Tilt (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given the &lt;code>root&lt;/code> of a binary tree, return &lt;em>the sum of every tree node&amp;rsquo;s&lt;/em> *&lt;strong>tilt&lt;/strong> *&lt;em>.&lt;/em>&lt;/p>
&lt;p>The &lt;strong>tilt&lt;/strong> 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>0&lt;/code>. The rule is similar if there the node does not have a right child.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-.jpg"
width="712"
height="182"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-_hu06680af7e30bdc59679b77cddde63754_10287_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_n3VDsKYOs5Tivyg-_hu06680af7e30bdc59679b77cddde63754_10287_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="391"
data-flex-basis="938px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tilt of node 2 : |0-0| = 0 (no children)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tilt of node 3 : |0-0| = 0 (no children)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;span style="display:flex;">&lt;span>Sum of every tilt : 0 + 0 + 1 = 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC.jpg"
width="800"
height="203"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC_hu46895bc0d53a45ff35a53b8976af6a23_14726_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_gkWZfWiksT5c-TsC_hu46895bc0d53a45ff35a53b8976af6a23_14726_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="394"
data-flex-basis="945px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [4,2,9,3,5,null,7]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 15
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tilt of node 3 : |0-0| = 0 (no children)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tilt of node 5 : |0-0| = 0 (no children)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tilt of node 7 : |0-0| = 0 (no children)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;span style="display:flex;">&lt;span>Sum of every tilt : 0 + 0 + 0 + 2 + 7 + 6 = 15
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l.jpg"
width="800"
height="293"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l_hu82bd868f2ed0b08cf837efe9d6811650_21438_480x0_resize_q75_box.jpg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-106-tree-19-dfs-16/0_kb1LkOQ2Kql9Po_l_hu82bd868f2ed0b08cf837efe9d6811650_21438_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="273"
data-flex-basis="655px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [21,7,14,1,1,2,2,3,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 9
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>The number of nodes in the tree is in the range &lt;code>[0, 104]&lt;/code>.&lt;/li>
&lt;li>&lt;code>-1000 &amp;lt;= Node.val &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，試計算二元樹的每個節點的tilt(坡度)和。&lt;/p>
&lt;p>什麼是tilt呢?&lt;br>
題目告訴我們，對於一個節點，&lt;br>
其左子樹的和以及右子樹的和相減的絕對值，&lt;br>
就稱為它的坡度(tilt)，當子樹不存在時，和則視為0。&lt;/p>
&lt;p>另外由於整個樹的總節點數已經被限定在0~104之間了，&lt;br>
表示我們可以放心的用遞迴！&lt;/p>
&lt;p>那麼，我們該怎麼對每個節點算坡度呢？&lt;br>
對於一個節點n，如果它不存在的話(NIL)，&lt;br>
&lt;strong>其坡度自然為0，且總和同樣為0&lt;/strong> ；&lt;br>
存在的話，我們必須先算出&lt;strong>左子樹(n.left為根節點的子樹)和，&lt;br>
以及右子樹(n.right為根節點的子樹)和，將兩者相減取絕對值，&lt;br>
就是n的坡度。&lt;/strong>&lt;/p>
&lt;p>因此，我們可以使用一個dfs的函式來同時處理算子樹和，&lt;br>
以及坡度的部分，整個dfs的概念應該會如下：&lt;/p>
&lt;ol>
&lt;li>若n為NIL，回傳0&lt;/li>
&lt;li>將n.left代入dfs中，取得n.left的子樹和l&lt;/li>
&lt;li>將n.right代入dfs中，取得n.right子樹和r&lt;/li>
&lt;li>將|l-r|加到物件變數的答案res中&lt;/li>
&lt;li>回傳l+r+n.val&lt;/li>
&lt;/ol>
&lt;p>留意到我們使用dfs的回傳一直都是回傳以n為根節點的子樹和，&lt;br>
這個和我們要計算的坡度不同，所以必須要用一個res變數來儲存。&lt;/p>
&lt;p>在寫出dfs函式後，我們只需要初始化res，&lt;br>
並且在主函式中呼叫dfs後，回傳res即可。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java-對於java而言abs在javalangmath函式庫中">Java 對於Java而言abs在java.lang.Math函式庫中，
&lt;/h3>&lt;p>如果不是在LeetCode的編輯器的話，不要忘記自行import。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e737e1f9dd68f2eca0b6352f790fb0a9.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分和Java大同小異，&lt;br>
這邊採用將dfs寫成一個子函式，別忘記要宣告以後才能夠使用呦！&lt;br>
此外，__init__並非一定要這樣使用，在class Solution中直接定義也沒問題。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/5420e6680c86b99d7f00c51bb3b55430.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(樹的深度)，最差則為O(N))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 105 Tree (18) / DFS (15) / Backtracking (7)</title><link>https://learnwithdesolve.netlify.app/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://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-105-tree-18-dfs-15-backtracking-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 105 Tree (18) / DFS (15) / Backtracking (7)" />&lt;p>&lt;strong>0437. Path Sum III (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下， &lt;strong>「從Leetcode學演算法｜進階篇」及&lt;/strong> 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p>
&lt;p>目前只剩下給讀者的&lt;strong>進階篇+面試篇(3150)&lt;/strong> 和&lt;strong>全套同捆優惠(3990)&lt;/strong> 了QQ&lt;br>
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;br>
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;p>內容介紹：&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are given a binary tree in which each node contains an integer value.&lt;/p>
&lt;p>Find the number of paths that sum to a given value.&lt;/p>
&lt;p>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>
&lt;p>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>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 5 -3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3 2 11
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3 -2 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Return 3. The paths that sum to 8 are:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>1. 5 -&amp;gt; 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2. 5 -&amp;gt; 2 -&amp;gt; 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3. -3 -&amp;gt; 11
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>&lt;strong>給定一個二元樹，當中每個節點均含一個整數，&lt;br>
找出所有可以加總等於目標總和的路徑數量。&lt;br>
一個路徑不需要從根節點開始，也不必一定要到葉節點結束，&lt;br>
但是路徑只能往下走(也就是說只能從父節點往子節點走)；&lt;br>
另外，這棵樹最多只會有1000個節點，&lt;br>
且其值均在-1000000~1000000之間。&lt;/strong>&lt;/p>
&lt;p>這一題是一整組Path Sum系列題的第三題。&lt;br>
由於題目提示節點數不會超過1000個，&lt;br>
所以基本是無法超過各程式的Call Stack限制，可以放心使用遞迴。&lt;/p>
&lt;p>那麼，我們看看另一個重點：&lt;br>
路徑只能往下走，會有什麼特點呢？&lt;br>
舉例來說，以上面的二元樹，當我們走到某個節點2時，&lt;br>
所有終點是2的路徑有以下三種：&lt;br>
10 -&amp;gt; 5 -&amp;gt; 2 &lt;br>
5 -&amp;gt; 2&lt;br>
2&lt;br>
再往下走到1的時候，路徑有以下四種：&lt;br>
&lt;strong>10 -&amp;gt; 5 -&amp;gt; 2&lt;/strong> -&amp;gt; 1&lt;br>
&lt;strong>5 -&amp;gt; 2&lt;/strong> -&amp;gt; 1&lt;br>
&lt;strong>2&lt;/strong> -&amp;gt; 1&lt;br>
1&lt;/p>
&lt;p>我們可以發現，走到1的路徑和到底有沒有符合target的解這件事情，&lt;br>
可以透過兩點知道：&lt;/p>
&lt;ol>
&lt;li>從root起算走到現在這個節點的總和是否和target相等&lt;/li>
&lt;li>從root起算走到現在這個節點的總和-target是否在過往出現過&lt;/li>
&lt;/ol>
&lt;p>第2點比較抽象，我們稍微舉一下簡單的例子：&lt;br>
假設我們要找的目標是8的話，&lt;br>
那麼直接看我們當然知道是5-&amp;gt;2-&amp;gt;1，&lt;br>
但如果不能回頭重算的話，要怎麼辦呢？&lt;br>
&lt;strong>我們可以得到5-&amp;gt;2-&amp;gt;1的路徑，&lt;br>
其實相當於從根節點10走到1的路徑和，減去節點10。&lt;/strong>&lt;/p>
&lt;p>換句話說，如果我們每走到一個節點，都將路徑和記錄下來，&lt;br>
那麼我們就可以用前面過往的路徑和，&lt;br>
來表達出所有達到現在這個節點的路徑和。&lt;/p>
&lt;p>例如：&lt;br>
1其實等於&lt;strong>10 -&amp;gt; 5 -&amp;gt; 2&lt;/strong> -&amp;gt; 1 去掉** 10 -&amp;gt; 5 -&amp;gt; 2&lt;br>
2** -&amp;gt; 1等於** 10 -&amp;gt; 5 -&amp;gt; 2** -&amp;gt; 1去掉** 10 -&amp;gt; 5&lt;br>
5 -&amp;gt; 2** -&amp;gt; 1等於** 10 -&amp;gt; 5 -&amp;gt; 2** -&amp;gt; 1去掉** 10**&lt;/p>
&lt;p>這樣足夠清楚了嗎XD？&lt;br>
因此，我們要做的事情有：&lt;br>
0. 建一個dictionary或hashmap，&lt;br>
當中key/value分別代表路徑和/路徑和出現的次數。&lt;br>
同時，將(0, 1)置入字典當中。(這裡稱之為preSum)&lt;br>
(方便我們在剛好等於根節點到當前節點總長時計算)&lt;/p>
&lt;ol>
&lt;li>
&lt;p>呼叫遞迴DFS函式並回傳其結果。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在DFS函式中，遍歷整棵二元樹：&lt;br>
2.0. 檢查節點是否存在，不存在則回傳0&lt;br>
2.1. 將當前的節點值加上根節點的値，做為現在的總和(currSum)&lt;br>
2.2. 初始化res，其值為currSum-target在preSum中出現的次數&lt;br>
2.3. 分別向左右節點遞迴呼叫DFS函式，將得到的結果加到res&lt;br>
2.4. 由於這條路徑只能一路向下，&lt;br>
所以要回到上一層前，&lt;br>
需將剛剛加過的1次記錄從preSum中扣掉(backtracking)。&lt;br>
2.5. 回傳res&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分preSum使用HashMap，留意先進行一次put，&lt;br>
再放入helper函式中做DFS；&lt;br>
helper函式中的部分，由於HashMap本身找不存在的值會出錯，&lt;br>
別忘了使用getOrDefault來給定預設值(當然，你要用containsKey也行)。&lt;br>
在遞迴取得左右兩邊節點的符合路徑數加總後，&lt;br>
別忘記回傳前要將加上去的刪掉，才符合回溯法的要件。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/5143526b20200b9535b866e51d91a96d.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分大同小異，&lt;br>
不同的是我們可以用defaultdict來將預設值當作0，&lt;br>
從Python的寫法中應該可以更清晰看見回溯法的樣貌。&lt;br>
(先加1後減1)&lt;br>
這邊的helper直接寫成子函式，&lt;br>
所以我們就不需使用self.xxx的形式來呼叫了。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/7e4a95c35aa33ed530333b6371dfcc1b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N*樹深)，每個節點均需要經過一次，&lt;br>
每個節點最多可以成立d個preSum值，&lt;br>
d為樹的深度，以平衡樹來說則是log(N))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 104 Tree (17) / DFS (14) / Backtracking (6)</title><link>https://learnwithdesolve.netlify.app/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://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-104-tree-17-dfs-14-backtracking-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 104 Tree (17) / DFS (14) / Backtracking (6)" />&lt;p>&lt;strong>0113. Path Sum II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下， &lt;strong>「從Leetcode學演算法｜進階篇」及&lt;/strong> 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p>
&lt;p>目前只剩下給讀者的&lt;strong>進階篇+面試篇(3150)&lt;/strong> 和&lt;strong>全套同捆優惠(3990)&lt;/strong> 了QQ&lt;br>
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;br>
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;p>內容介紹：&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> A leaf is a node with no children.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;p>Given the below binary tree and &lt;code>sum = 22&lt;/code>,&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 11 13 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>7 2 5 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Return:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [5,4,11,2],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [5,8,4,5]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>分析/解題&lt;br>
給定一個二元樹以及目標的和(sum)，找出所有根節點到葉的路徑，這些路徑各自的和要等於給定的和。&lt;/strong>&lt;/p>
&lt;p>這一題是一整組Path Sum系列題的第二題。&lt;br>
由於要找出路徑，所以我們需要一組記錄當前路徑current的位置的list。&lt;br>
同時，要能夠判定是否要確認這條路徑OK的狀態，&lt;br>
只取決於現在是否走到葉節點(因為題目要求)；&lt;br>
並且走到葉節點時，左右也都沒有節點了，就無法往下走。&lt;/p>
&lt;p>我們可以用一個result的list記錄最終處理完的結果，&lt;br>
接著使用&lt;strong>DFS&lt;/strong> 的方式往下找。&lt;/p>
&lt;p>那麼自然我們每走過一個節點，&lt;br>
就要將sum減去現在root的値，同時記錄到current上。&lt;/p>
&lt;p>接下來要往下走還是檢查呢？&lt;br>
當然就是看左右節點是否為NIL且sum和root的値是否相等啦！&lt;br>
如果是的話，可以將result加上走到現在的路徑；&lt;br>
如果不是的話，則以DFS往左和往右走(不要忘記去檢查NIL的狀況)。&lt;br>
這整段走完要回到上一層的時候，表示已經處理完了，&lt;br>
&lt;strong>不要忘記我們先前將這層root的値放進了current裡面，&lt;br>
所以我們應該要將其移除。&lt;/strong>(** Backtracking**的部分)&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分我們可以使用同名但不同參數長度的函式，&lt;br>
直接利用開頭檢查root，&lt;br>
來順便處理後續帶入root.left/root.right所需要的檢查。&lt;br>
Backtracking的部分，&lt;br>
currentResult先加上root.val後，後續再進行remove即可；&lt;br>
而留意由於我們不斷地在變換currentResult，&lt;br>
不要忘記要將其複製一份以加到result裡面，而非直接用加的。&lt;br>
(使用&lt;strong>new LinkedList(currentResult)&lt;/strong> )&lt;/p>
&lt;script src="https://gist.github.com/Desolve/6d08f8daf783bd267da27465c43c98fe.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>同理，Python的部分一樣需要複製，&lt;br>
我們可以寫成curr[:]以複製一份用來讓res進行附加。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/384a6f215dc4c816f3bbdb93edbe8fb8.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(logN)，因為整棵樹要遍歷過一遍，&lt;br>
然後平均而言，樹的深度會到O(logN)，&lt;br>
所以空間複雜度所以空間複雜度，這個部分不包含result的占用空間)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 103 Tree (16) / DFS (13) / BFS (3) / Queue (4)</title><link>https://learnwithdesolve.netlify.app/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://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-103-tree-16-dfs-13-bfs-3-queue-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 103 Tree (16) / DFS (13) / BFS (3) / Queue (4)" />&lt;p>&lt;strong>0112. Path Sum (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下， &lt;strong>「從Leetcode學演算法｜進階篇」及&lt;/strong> 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p>
&lt;p>目前只剩下給讀者的&lt;strong>進階篇+面試篇(3150)&lt;/strong> 和&lt;strong>全套同捆優惠(3990)&lt;/strong> 了QQ&lt;br>
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;br>
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;p>內容介紹：&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;/p>
&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>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>
&lt;p>&lt;strong>Note:&lt;/strong> A leaf is a node with no children.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;p>Given the below binary tree and &lt;code>sum = 22&lt;/code>,&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 11 13 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>7 2 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>return true, as there exists a root-to-leaf path &lt;code>5-&amp;gt;4-&amp;gt;11-&amp;gt;2&lt;/code> which sum is 22.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一棵二元樹，試決定該二元樹是否有一個從根到葉的路徑，&lt;br>
使得路徑上的節點總和恰等於給定的目標和。&lt;/p>
&lt;p>這一題是一整組Path Sum系列題的第一題，&lt;br>
除了接下來幾篇會陸續談到系列題外，這篇也想著重給讀者一個提醒：&lt;br>
&lt;strong>很多時候能用DFS解的題目，通常也能用BFS解&lt;/strong> (反之亦然)&lt;/p>
&lt;p>所以當下遇到一個題目的時候，除非有限定要求，&lt;br>
否則只要&lt;strong>能想到的解法就是好解法&lt;/strong> ，&lt;br>
不要硬逼自己一定要用DFS或一定要用BFS。&lt;br>
(練習的時候，當然還是可以自我挑戰兩種都想出解來就是了XD)&lt;/p>
&lt;p>首先我們要留意到一件事情：&lt;br>
由於是從根到葉，&lt;br>
所以我們只需要在走到左右均無節點時再檢查總和是否相符即可，&lt;br>
千萬不要沿途檢查呀XD！&lt;/p>
&lt;p>再者，由於路途經過的都會算做計入的總和，&lt;br>
所以我們可以沿路將往下走所需的總和減去當前經過的節點。&lt;/p>
&lt;p>依照這個概念，我們可以蠻直觀地寫出一個DFS的解：&lt;/p>
&lt;ol>
&lt;li>先檢查&lt;strong>root如果是NIL -&amp;gt; 直接回傳False&lt;/strong>&lt;/li>
&lt;li>檢查&lt;strong>root.left/root.right&lt;/strong> 是不是&lt;strong>都為NIL&lt;/strong> -&amp;gt; 若均為NIL，&lt;br>
若&lt;strong>root.val等於所需和&lt;/strong> 則回傳&lt;strong>True&lt;/strong> ，&lt;strong>否則回傳False&lt;/strong>&lt;/li>
&lt;li>將往下走的剩下的和next定為sum — root.val(剩下需要湊的和)&lt;/li>
&lt;li>回傳&lt;strong>hasPathSum(root.left, next) || hasPathSum(root.right, next)&lt;/strong> (因為只要存在一條路徑即為True，所以兩者用&lt;strong>或&lt;/strong> 來連接)&lt;/li>
&lt;/ol>
&lt;p>由上可知，用來判定這個位置能不能成為我們要的路徑和，&lt;br>
只取決於兩點：&lt;/p>
&lt;ol>
&lt;li>現在這個位置是否已經是葉(leaf)&lt;/li>
&lt;li>現在這個位置的値是否是剩下需要的和&lt;/li>
&lt;/ol>
&lt;p>所以我們也可以用BFS的方式，搭配前面講過的Queue來處理：&lt;/p>
&lt;ol>
&lt;li>同樣先檢查root及處理回傳&lt;/li>
&lt;li>將**[(root, sum - root.val)]** 放入Queue當中&lt;/li>
&lt;li>進行迴圈，每次從Queue中取出一組**(curr, val)** 並檢查：&lt;br>
3–1. 若curr.left/curr.right&lt;strong>均為NIL&lt;/strong> -&amp;gt; ** 若val為0，回傳True**&lt;br>
3–2. 檢查curr.left，若存在 -&amp;gt; 將**(curr.left, val - curr.left.val)放入Queue** 中&lt;br>
3–3. 對curr.right做相同處理&lt;/li>
&lt;li>若迴圈結束仍未回傳，則&lt;strong>回傳Fals&lt;/strong> e(找不到適合的路徑)&lt;/li>
&lt;/ol>
&lt;p>依上面的方式，我們分別在Java/Python演示不同的方法：&lt;br>
(讀者也可以自行嘗試完整練完單一語言的DFS/BFS的方法)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，使用了DFS，所以整體而言看起來很簡單，&lt;br>
不過原則上有用遞迴的題目，就盡量要留意call stack的深度會不會超過。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/ef96d203f2d348e11ecc39418a6ddb46.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分則使用了BFS，搭配deque做為queue使用，&lt;br>
留意當val != 0的時候記得要繼續操作，因為你可能會有其他節點符和XD，&lt;br>
這點和DFS時不一樣，請特別留意不要直接在那邊回傳False呦！&lt;/p>
&lt;script src="https://gist.github.com/Desolve/43e22de9d28607e24276588dc0aaf675.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(log N)或O(N)(平均)，&lt;br>
因為DFS的話記憶體計算call stack深度，&lt;br>
BFS的話則是要用最底部的橫向長度來看；&lt;br>
如果極端的狀況的話DFS也有可能到O(N)，因為樹可能不平衡)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 102 Tree (15) / DFS (12)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/</link><pubDate>Fri, 31 Jul 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 102 Tree (15) / DFS (12)" />&lt;p>&lt;strong>1530. Number of Good Leaf Nodes Pairs (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>期限嘛&amp;hellip;就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given the &lt;code>root&lt;/code> of a binary tree and an integer &lt;code>distance&lt;/code>. A pair of two different &lt;strong>leaf&lt;/strong> 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>distance&lt;/code>.&lt;/p>
&lt;p>Return &lt;em>the number of good leaf node pairs&lt;/em> in the tree.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001.png"
width="321"
height="321"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001_hu38c80e3bb9f2f6fa441fee965063aa00_28155_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-001_hu38c80e3bb9f2f6fa441fee965063aa00_28155_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,2,3,null,4], distance = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002.png"
width="441"
height="321"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002_hu19dfa5f4b086aff8df1c0c6709b9942f_34621_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-102-tree-15-dfs-12/image-002_hu19dfa5f4b086aff8df1c0c6709b9942f_34621_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="137"
data-flex-basis="329px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,2,3,4,5,6,7], distance = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [7,1,4,6,null,5,3,null,null,null,null,null,2], distance = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The only good pair is [2,5].
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [100], distance = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-5">Example 5
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,1,1], distance = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>The number of nodes in the &lt;code>tree&lt;/code> is in the range &lt;code>[1, 2^10].&lt;/code>&lt;/li>
&lt;li>Each node’s value is between &lt;code>[1, 100]&lt;/code>.&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= distance &amp;lt;= 10&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>這題是2020/07/26舉辦的199th LeetCode Weekly Contest的第3題。&lt;br>
給定一個二元樹的根節點root和一個整數距離distance，&lt;br>
如果兩個不同的葉節點配對，其最小距離小於等於distance，&lt;br>
我們就將其稱之為好(good)。&lt;br>
試回傳這棵樹好的葉節點配對的總數。&lt;/p>
&lt;p>我們先前應該已經提到過葉節點就是指&lt;strong>左右都沒有連接節點的節點&lt;/strong> ，&lt;br>
那麼，這題要怎麼思考呢？&lt;/p>
&lt;p>我們不妨先留意一下題目給定的條件：&lt;br>
節點數量是1~2¹⁰，由於&lt;strong>2¹⁰=1024&lt;/strong> ，所以最壞的狀況，&lt;br>
遞迴的數量也就1024而已，所以應該可以不會超過call stack的上限。&lt;br>
接著，1≤distance≤10決定了我們在遞迴時，&lt;br>
可以適度修剪我們要處理的節點。&lt;/p>
&lt;p>那這題該怎麼思考呢？&lt;br>
由於我們在求的是最短距離，假定我們要看兩個節點x, y，&lt;br>
那麼&lt;strong>最短路徑肯定是從x往上走到x, y的最低共同祖先，&lt;br>
再往下走到y的位置&lt;/strong>。&lt;/p>
&lt;p>如果我們知道x, y的LCA(最低共同祖先)n，&lt;br>
又知道n的左子樹的所有葉節點各自的深度，&lt;br>
及右子樹的所有葉節點各自的深度，&lt;br>
那麼我們就可以知道以n為LCA時，正確的節點對有哪些。&lt;br>
怎麼知道？就迴圈加起來就好了嘛！&lt;/p>
&lt;p>那我們又怎麼知道某個節點n的左右子樹的葉節點深度呢？&lt;br>
我們可以先用dfs往深處走，走到出現葉節點的時候，&lt;br>
將其記錄為距離1並往上傳(因為這時候左右也都沒得走了)；&lt;/p>
&lt;p>那在某個非葉節點的&lt;strong>n&lt;/strong> 時，我們應該可以從dfs的結果，&lt;br>
分別獲得&lt;strong>左右子樹的各個葉節點離n的距離&lt;/strong> 。&lt;br>
我們將兩個距離的列表分別叫作&lt;strong>llt跟rlt&lt;/strong> (left list, right list)，&lt;br>
從llt跟rlt分別成對取出來相加，&lt;br>
每發現一組葉節點距離相加&lt;strong>小於等於10，全局的解就加1&lt;/strong> 。&lt;/p>
&lt;p>做完檢查以後該做什麼呢？&lt;br>
裡面所有的葉節點應該可以往上通用，對吧？&lt;br>
可是我們左子樹和右子樹往上都導到當前的節點再往上，&lt;br>
&lt;strong>再往上的深度應該都要加1&lt;/strong> 才對！&lt;br>
所以我們應該將llt和rlt裡面的所有值都分別+1以後，&lt;br>
&lt;strong>放入一個新的list，這裡命名為merge，再將其往上傳。&lt;/strong>&lt;/p>
&lt;p>因此，整個流程會大致如下：&lt;/p>
&lt;ol>
&lt;li>定一個class變數cnt，用來記錄成功配對的葉節點對的總數&lt;/li>
&lt;li>在主函式裡，先檢查root是否為NIL，是的話直接回傳0&lt;/li>
&lt;li>將root和distance帶入遞迴函式dfs中&lt;/li>
&lt;li>回傳cnt&lt;/li>
&lt;/ol>
&lt;p>而在dfs函式中，我們要做的事情是：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>若n為NIL，回傳空的串列&lt;/strong>&lt;/li>
&lt;li>若&lt;strong>n的左右節點均為NIL&lt;/strong> ，則回傳一個&lt;strong>裡面只含一個1的串列&lt;/strong>&lt;/li>
&lt;li>呼叫&lt;strong>dfs(n.left, distance)&lt;/strong> 及&lt;strong>dfs(n.right, distance)&lt;/strong> 進行遞迴，&lt;br>
取得回傳的&lt;strong>llt&lt;/strong> 跟&lt;strong>rlt&lt;/strong> (記錄兩邊葉節點深度的串列)&lt;/li>
&lt;li>初始化一個空的串列&lt;strong>merge&lt;/strong>&lt;/li>
&lt;li>雙重迴圈，每當遇到llt和rlt的値**，&lt;br>
兩兩相加會小於等於distance&lt;strong>的狀況，就將&lt;/strong> cnt遞增1**&lt;/li>
&lt;li>分別將llt和rlt的値全數+1後，&lt;strong>加到merge&lt;/strong> 裡&lt;br>
(這邊可以檢查&lt;strong>值必須小於distance&lt;/strong> ，超過的話因為&lt;strong>總路徑肯定超過，&lt;/strong> 所以不符的不用放到merge內)&lt;/li>
&lt;li>&lt;strong>回傳merge&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>由於需要一個一個取出，並且重複使用，&lt;br>
所以我們使用&lt;strong>ArrayList&lt;/strong> 並使用&lt;strong>get&lt;/strong> 來取得當中的值。&lt;br>
在雙重迴圈的時候，我們可以&lt;strong>順便將外層的値處理一下放到merge內&lt;/strong> ，&lt;br>
這樣後面就不用再重複一個新的迴圈處理。&lt;br>
&lt;strong>(但內層的不能這麼做，因為會被重複執行)&lt;/strong>&lt;/p>
&lt;script src="https://gist.github.com/Desolve/0d13365f3b888363162a345bf51f0fe6.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，cnt的累計可以使用list comprehension，&lt;br>
&lt;strong>處理符合的配對再來取len()&lt;/strong> ，這樣寫起來會比雙重迴圈方便許多。&lt;br>
llt和rlt則可以用類似的方式，最後將串列用加號組起來回傳。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/22ee498949dc5de4760ee139d546431e.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O((log N)³)/O(log N)，因為只有葉節點需要被記錄，&lt;br>
空間應該跟最底層的節點數有關，而除了雙重迴圈外，&lt;br>
dfs的深度也跟這棵樹的深度有關，但這個部分會受到distance的制約，&lt;br>
所以實際應該比這個複雜度快不少)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 101 String (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-101-string-6/</link><pubDate>Sun, 26 Jul 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-101-string-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 101 String (6)" />&lt;p>&lt;strong>1529. Bulb Switcher IV (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br>
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
>&lt;strong>Python Taiwan的連結第100篇的文章&lt;/strong> &lt;/a>底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>&lt;strong>截止時間為7/31 23:59:59，這之後的留言問題我有看到還是會回答，&lt;br>
但就不會納入抽獎資格歐！&lt;/strong>&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;/p>
&lt;p>當前面試篇以上傳完畢，進階篇則會在8/31前陸續上傳完成呦！&lt;/p>
&lt;p>有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>There is a room with &lt;code>n&lt;/code> bulbs, numbered from &lt;code>0&lt;/code> to &lt;code>n-1&lt;/code>, arranged in a row from left to right. Initially all the bulbs are &lt;strong>turned off&lt;/strong> .&lt;/p>
&lt;p>Your task is to obtain the configuration represented by &lt;code>target&lt;/code> where &lt;code>target[i]&lt;/code> is &amp;lsquo;1&amp;rsquo; if the i-th bulb is turned on and is &amp;lsquo;0&amp;rsquo; if it is turned off.&lt;/p>
&lt;p>You have a switch to flip the state of the bulb, a flip operation is defined as follows:&lt;/p>
&lt;ul>
&lt;li>Choose &lt;strong>any&lt;/strong> bulb (index &lt;code>i&lt;/code>) of your current configuration.&lt;/li>
&lt;li>Flip each bulb from index &lt;code>i&lt;/code> to &lt;code>n-1&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>When any bulb is flipped it means that if it is 0 it changes to 1 and if it is 1 it changes to 0.&lt;/p>
&lt;p>Return the &lt;strong>minimum&lt;/strong> number of flips required to form &lt;code>target&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: target = &amp;#34;10111&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Initial configuration &amp;#34;00000&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>flip from the third bulb: &amp;#34;00000&amp;#34; -&amp;gt; &amp;#34;00111&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>flip from the first bulb: &amp;#34;00111&amp;#34; -&amp;gt; &amp;#34;11000&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>flip from the second bulb: &amp;#34;11000&amp;#34; -&amp;gt; &amp;#34;10111&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>We need at least 3 flip operations to form target.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: target = &amp;#34;101&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: &amp;#34;000&amp;#34; -&amp;gt; &amp;#34;111&amp;#34; -&amp;gt; &amp;#34;100&amp;#34; -&amp;gt; &amp;#34;101&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: target = &amp;#34;00000&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: target = &amp;#34;001011101&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= target.length &amp;lt;= 10^5&lt;/code>&lt;/li>
&lt;li>&lt;code>target[i] == '0'&lt;/code> or &lt;code>target[i] == '1'&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>這題是今天(2020/07/26)舉辦的199th LeetCode Weekly Contest的第2題。&lt;br>
房間裡有n個燈泡**(0~n-1)** ，從左至右排列，&lt;strong>初始全數是關的&lt;/strong> 。&lt;br>
我們的目標是將燈開關成&lt;strong>target&lt;/strong> 的狀態，在index i的位置上，&lt;br>
target[i]如果是'1&amp;rsquo;的話就表示開，target[i]如果是'0&amp;rsquo;的話就表示關。&lt;/p>
&lt;p>所能夠做的操作只有一種叫&lt;strong>flip&lt;/strong> 的方法。&lt;br>
flip方法的操作是選取一個index i，&lt;br>
接著會將&lt;strong>i~n-1的所有燈泡狀態反轉，1變成0，0變成1&lt;/strong> 。&lt;/p>
&lt;p>我們要作的事情是找出最少完成target的flip次數。&lt;/p>
&lt;p>是說每次碰到稍微生活化一點的題目，就會覺得有點87：&lt;br>
像這題亮燈就亮燈，搞那麼麻煩的開關方式幹嘛啦！！！&lt;br>
不怕燈泡壞掉逆？？？&lt;/p>
&lt;p>這題乍看之下好像不容易，&lt;br>
但仔細一看，flip的操作只影響該點及其右側的燈泡，&lt;br>
所以我們由左往右看的話，只需要考慮&lt;strong>當前該燈泡需不需要翻轉&lt;/strong> 即可，&lt;br>
因為某個點右側的燈泡flip不會影響該點。&lt;/p>
&lt;p>由於&lt;strong>右邊的會一起反轉&lt;/strong> ，所以我們可以定位一個&lt;strong>flag=1&lt;/strong> ，&lt;br>
一開始大家都是0，所以第一次我們要翻轉的狀況，&lt;br>
就是碰到&lt;strong>target[i]和flag相等時。&lt;/strong> 把右側翻過來以後，我們可以&lt;strong>將flag從'1&amp;rsquo;變成'0&amp;rsquo;，&lt;/strong>&lt;br>
因為我們只要&lt;strong>考慮翻或不翻&lt;/strong> ，所以使用&lt;strong>flag的變化&lt;/strong> ，&lt;br>
&lt;strong>和target[i]碰到的値來作對照&lt;/strong> 會相當方便：&lt;br>
只要&lt;strong>碰到和flag相同的就代表要加翻一次&lt;/strong> ，&lt;br>
&lt;strong>不同的就代表不用翻&lt;/strong> ，這樣沿路走到尾端，就可以得到計數的答案。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分使用charAt可以按char來取出每個字元，&lt;br>
請留意要比較的時候要取成int，這邊直接減去’0’即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/3e614bbf0081bb52a5b31742bbe5b3c9.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分直接用int進行轉換字元成整數即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/04a5a55c90c881ab1661f4271cd2e10f.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(len(target))/O(1)，除了flag跟cnt以外並未額外再多用到其他空間)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 100 Dynamic Programming (14)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-100-dynamic-programming-14/</link><pubDate>Mon, 20 Jul 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-100-dynamic-programming-14/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 100 Dynamic Programming (14)" />&lt;p>&lt;strong>1510. Stone Game IV (Hard)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>扣掉第0篇外，這篇是100篇啦！！！**從開始寫以來，一路到現在其實也不容易，&lt;br>
雖然頻率因為工作和開課的關係降低很多，&lt;br>
但希望大家仍然從文章中能有所收穫。&lt;/p>
&lt;p>100篇好像應該要來個感恩回饋(?)&lt;br>
那這樣好了，如果有任何問題，&lt;br>
歡迎在本篇底下發問(Python Taiwan也可以)，&lt;br>
同時請在&lt;strong>Python Taiwan的連結本篇文的文章&lt;/strong> 底下，&lt;br>
&lt;strong>公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong>&lt;br>
&lt;strong>「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br>
「除了從LeetCode學演算法系列以外，&lt;br>
你還想要看到關於什麼方向的文章？」&lt;/strong>&lt;br>
&lt;strong>超過20則留言的話&lt;/strong> (有完成以上步驟的才算)，我們就抽一組&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br>
課程的免費兌換券進行贈送！&lt;/strong>&lt;/p>
&lt;p>&lt;strong>截止時間為7/31 23:59:59，這之後的留言問題我有看到還是會回答，&lt;br>
但就不會納入抽獎資格歐！&lt;/strong>&lt;/p>
&lt;p>如果留言人數不足的話，&lt;br>
那我可能就以一篇文章的形式來回應大家的問題，&lt;br>
就不會進行抽獎囉XD&lt;/p>
&lt;p>感謝大家的支持與肯定，期待我們都能從這當中(我寫文章，你們讀文章XD)&lt;br>
不斷成長，進而提升自己的程式能力！&lt;/p>
&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！面試篇已經全數上傳啦~&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Alice and Bob take turns playing a game, with Alice starting first.&lt;/p>
&lt;p>Initially, there are &lt;code>n&lt;/code> stones in a pile. On each player&amp;rsquo;s turn, that player makes a &lt;em>move&lt;/em> consisting of removing &lt;strong>any&lt;/strong> non-zero ** square number** of stones in the pile.&lt;/p>
&lt;p>Also, if a player cannot make a move, he/she loses the game.&lt;/p>
&lt;p>Given a positive integer &lt;code>n&lt;/code>. Return &lt;code>True&lt;/code> if and only if Alice wins the game otherwise return &lt;code>False&lt;/code>, assuming both players play optimally.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Alice can remove 1 stone winning the game because Bob doesn&amp;#39;t have any moves.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Alice can only remove 1 stone, after that Bob removes the last one winning the game (2 -&amp;gt; 1 -&amp;gt; 0).
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: n is already a perfect square, Alice can win with one move, removing 4 stones (4 -&amp;gt; 0).
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 7
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Alice can&amp;#39;t win the game if Bob plays optimally.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>If Alice starts removing 4 stones, Bob will remove 1 stone then Alice should remove only 1 stone and finally Bob removes the last one (7 -&amp;gt; 3 -&amp;gt; 2 -&amp;gt; 1 -&amp;gt; 0).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>If Alice starts removing 1 stone, Bob will remove 4 stones then Alice only can remove 1 stone and finally Bob removes the last one (7 -&amp;gt; 6 -&amp;gt; 2 -&amp;gt; 1 -&amp;gt; 0).
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-5">Example 5
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 17
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Alice can&amp;#39;t win the game if Bob plays optimally.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>Alice和Bob玩不膩的撿石頭遊戲又來啦！&lt;br>
這次一樣是Alice先開始，一堆石頭裡面有n個石頭，每次玩家行動時，&lt;br>
可以選擇拿走某個非0的平方數的石頭數量，稱為一次行動。&lt;br>
(也就是1的平方、2的平方、3的平方&amp;hellip;等)&lt;br>
當有人無法作任何行動的時候(也就是沒有任何石頭能拿)，就輸惹QQ&lt;br>
給定正整數n代表石頭的個數，如果Alice確定可以贏遊戲的話，&lt;br>
就回傳True，反之則回傳False。(假定雙方都採最佳的策略來進行)&lt;/p>
&lt;p>由於每次要拿非0的平方數，所以不能pass，&lt;br>
這就保證了遊戲一定會結束，&lt;br>
因為最後一定會拿到空掉，下一個人會輸掉。&lt;/p>
&lt;p>我們來考慮一下前面幾個狀況，來觀察一下有沒有什麼規律：&lt;br>
n = 0: False -&amp;gt; 顯然就是輸了嘛XD&lt;br>
n = 1: True -&amp;gt; Alice拿走1顆(1²)，由於拿光了，所以Alice贏。&lt;br>
n = 2: False -&amp;gt; Alice只能選擇拿1顆，Bob再拿1顆就沒了，Alice輸掉。&lt;br>
n = 3: True -&amp;gt; 只有1, 1, 1的選擇，所以Alice贏&lt;br>
n = 4: True -&amp;gt; Alice拿走4顆(2²)，直接獲勝&lt;/p>
&lt;p>看起來好像沒有很明顯對吧？&lt;br>
但這邊可以從題目中思考到一個關鍵，由於雙方都是以最好的策略，&lt;br>
也就是&lt;strong>Bob不會該贏卻沒贏&lt;/strong> ，所以以下兩點是我們可以確定的：&lt;br>
&lt;strong>1. 當n直接是完全平方數時，Alice可以贏&lt;/strong>&lt;br>
&lt;strong>2. 當n=x會讓Bob贏(Alice輸)的時候，n在以下狀況時Alice會贏：&lt;/strong>&lt;br>
&lt;strong>x+1, x+4, x+9, x+16…&lt;/strong>&lt;br>
因為這時候Alice只要拿掉對應的石頭，讓Bob碰到x的狀況，&lt;br>
這時候就反而變成Bob會輸了！&lt;br>
&lt;strong>(Alice先拿會輸的狀況，換成Bob先拿也會輸)&lt;/strong>&lt;/p>
&lt;p>由於這個狀況只限定於我們發現前一個False，&lt;br>
所以我們必須從已經確定的值去推論，&lt;br>
假設今天我們想要知道&lt;strong>n = i的值是否為True&lt;/strong> ，&lt;br>
我們需要先知道&lt;strong>n=0~i-1的值&lt;/strong> ，&lt;br>
接著檢查是否有任何一個&lt;strong>n=i-j²&lt;/strong> 的結果是&lt;strong>False&lt;/strong> (留意&lt;strong>j²要小於等於i&lt;/strong> )&lt;br>
只要有一個符合，那n=i的值就是True，&lt;br>
如果全部檢查完都沒有的話，n=i的值即為False。&lt;br>
由於n=i的值會跟前面n=i-j²的結果有關係，&lt;br>
這是一個很明顯的動態規劃的題目。&lt;/p>
&lt;p>因此，我們的程式流程應該像這樣：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>先初始化dp的陣列&lt;/strong> ，其長度為n+1，並先全初始化成False。&lt;/li>
&lt;li>執行一個迴圈，讓&lt;strong>i從1~n (0已經是False了直接跳過)&lt;/strong> ：&lt;br>
2-1. 在裡面再開一個迴圈，讓j從1遞增到&lt;strong>最大j² == i&lt;/strong> 為止&lt;br>
2-2. &lt;strong>若dp[i - j²]為False，將dp[i]設為True&lt;/strong> 並且&lt;strong>break&lt;/strong> 離開這層迴圈&lt;br>
(已經確定True就不用往下找了)&lt;/li>
&lt;li>整個雙層迴圈完成後，我們應該處理完成了整個dp的陣列，&lt;br>
只要&lt;strong>回傳dp[n]&lt;/strong> 即可。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，由於boolean陣列初始化的預設值就是False，&lt;br>
就不用額外作初始化了。(C++的話還是記得要初始化啊！)&lt;br>
要使用ArrayList也可以，但長度確定固定的話，其實直接開陣列比較快。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/acd48dc4a54ef456891392ce66320d20.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，我們當然也可以一路append，&lt;br>
但直接初始化串列比較乾脆，內層的迴圈則使用while來檢查條件，&lt;br>
不要忘記每次將j遞增。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1cd994d7e2b4551ab9da30c503583717.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(&lt;strong>O(n^(3/2))/O(n)&lt;/strong> 外層迴圈要跑n次，內層最大是根號n；&lt;br>
空間上使用dp的陣列/串列外，沒有額外的需求了)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-61-dynamic-programming-9-784b21b36c47?sk=5ef10c13e32c0b2dcf6e25420b7f7141" target="_blank" rel="noopener"
>1140. Stone Game II (Medium)&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>&lt;strong>別忘了，要抽獎的讀者記得去Python Taiwan按讚留言分享歐！&lt;/strong>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 99 Tree (14) / DFS (11)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-99-tree-14-dfs-11/</link><pubDate>Mon, 13 Jul 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-99-tree-14-dfs-11/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 99 Tree (14) / DFS (11)" />&lt;p>&lt;strong>0404. Sum of Left Leaves (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Find the sum of all left leaves in a given binary tree.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 20
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 15 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，試求所有左葉子的總和。&lt;/p>
&lt;p>我們很久以前有提過二元樹的定義，&lt;br>
忘記的話，請再複習一下XD&lt;br>
&lt;strong>而葉子的定義，就是它左右都沒有連接節點(NIL)！&lt;/strong>&lt;/p>
&lt;p>這時候，你可能會說：&lt;br>
我知道，那我只要一直往左邊看就好啦！&lt;/p>
&lt;p>呃&amp;hellip;&amp;hellip;同學，你忘記了你的&lt;strong>右子樹也可能產生左葉子&lt;/strong> 嗎XD？&lt;br>
範例中的15，不就是先從3的右節點20，&lt;br>
再往左節點來到15所得到的嗎？&lt;/p>
&lt;p>那怎麼辦呢？&lt;br>
所以我們在檢查所在節點是不是葉子的時候，&lt;br>
還需要看看這個節點是不是&lt;strong>從它的根節點往左邊走下來&lt;/strong> 的。&lt;br>
因此，我們可以每次分支往左右走，給出一個參數from，&lt;br>
分別&lt;strong>給往左子樹走的函式1，給右子樹走的函式-1&lt;/strong> ，&lt;br>
用來代表下一層的時候拿來判定是不是左葉子的前置依據。&lt;/p>
&lt;p>當我們看到from == 1且左右節點均為NIL時，&lt;br>
就可以將當前的節點值回傳，&lt;br>
否則的話，就繼續遞迴往下找底下子樹當中左葉的和。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，每次先檢查root是否為null，&lt;br>
接著我們的答案就用&lt;br>
&lt;strong>sumOfLeftLeaves(root.left, 1) + sumOfLeftLeaves(root.right, -1)&lt;/strong>&lt;br>
來取得。&lt;br>
其他的寫法概念如前所述。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/b8babe98eabb5f320c2d4952787a4a89.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分寫一個子函式，因為這邊沒有用self，&lt;br>
所以可以不用self.getSum來算。&lt;br>
(也可以把add設定預設値-1，&lt;br>
使用單個sumOfLeftLeaves來解此題，&lt;br>
這個化簡方式很簡單，就留給讀者來練習看看XD)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/24d3e49c96c5c0928d166dd35c6fbcaa.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，因為要經過每個節點，&lt;br>
而如果考慮call stack的話，&lt;br>
空間複雜度會是O(depth of Tree))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&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"
>0235. Lowest Common Ancestor of a Binary Search Tree (Easy)&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 面試篇宣傳</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-chapter-interview/</link><pubDate>Sun, 12 Jul 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-chapter-interview/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 面試篇宣傳" />&lt;p>&lt;strong>透過聆聽不同的工程師訪談，培養能力並抓住面試的機會&lt;/strong>&lt;/p>
&lt;p>由於剛好上架完了面試篇的所有內容，所以想來跟大家介紹一下。&lt;br>
在面試篇當中，我們整理了一些各種面試常出現的題型，&lt;br>
以及幫助你初步推測解題方向的方法；&lt;br>
同時，我們訪問了四位工程師：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>LiuLiu&lt;/strong> , HiSKIO的後端工程師，主要使用PHP+Laravel&lt;/li>
&lt;li>&lt;strong>Andy&lt;/strong> , Aimazing的前端工程師，主要使用Javascript+Vue.js&lt;/li>
&lt;li>&lt;strong>Mike&lt;/strong> , 資深前端工程師，&lt;br>
也是擁有&lt;strong>7門線上課程&lt;/strong> 和&lt;a class="link" href="https://www.youtube.com/ChengMike" target="_blank" rel="noopener"
>&lt;strong>YouTube頻道&lt;/strong> &lt;/a>的前端講師&lt;/li>
&lt;li>&lt;strong>Kenji&lt;/strong> , 資深軟體工程師，目前在矽谷的Square工作&lt;br>
(一家FinTech電子支付公司)&lt;br>
(同時他也有一個Podcast: &lt;a class="link" href="https://www.facebook.com/jktech.io/" target="_blank" rel="noopener"
>Just Kidding Tech 輕鬆談科技&lt;/a>)&lt;/li>
&lt;/ol>
&lt;p>由於涵蓋了不同資歷和定位的工程師的視角，&lt;br>
你可以從不同的受訪者身上，看到他們的觀點的差異，&lt;br>
以及不同時期的工程師所需要的技能有什麼。&lt;/p>
&lt;p>這門面試課是&lt;strong>和進階課綁定，不另行收費&lt;/strong> ，個人覺得相當之划算。&lt;br>
當初原本只是一個附帶的構想，但為了想要給出足夠完整的東西，&lt;br>
&lt;strong>最後就變得反而讓我做到很崩潰XD&lt;/strong>&lt;/p>
&lt;p>當然，成果也是可喜的，我從訪談的交流過程中，&lt;br>
除了得到有用的資訊外，也常常被逗樂。&lt;/p>
&lt;p>&lt;strong>比方說Mike就告訴我們：&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>我就是Code我就會忘阿，我就是靠編輯器來幫我提示阿，&lt;br>
我就是哪有辦法這樣寫得出來，我就覺得莫名其妙耶你知道嗎？&lt;br>
工程師考試那沒有提供電腦，那叫我拿紙筆寫，又不是在寫作文。&lt;/p>
&lt;/blockquote>
&lt;p>+1&lt;/p>
&lt;p>&lt;strong>Kenji則說：&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>你看太看重那個失敗本身，你太看重你被拒絕這件事情的話，&lt;br>
你反而會很難再繼續面試，因為你這個東西就是一個拒絕的過程。&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>人總會有被打槍的時候嘛XD&lt;/p>
&lt;p>面試如是，人生如是，總會有種種的挫折，&lt;br>
但我由衷希望，我的文章和課程，&lt;br>
能帶給所有正準備挑戰工程師的面試的人幫助。&lt;/p>
&lt;p>所以，有興趣的話，就考慮一下吧！&lt;br>
如果有希望我開什麼樣的內容或寫什麼方向的文章的話，&lt;br>
也可以留言告訴我～&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 98 Tree (13) / DFS (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-98-tree-13-dfs-10/</link><pubDate>Sat, 27 Jun 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-98-tree-13-dfs-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 98 Tree (13) / DFS (10)" />&lt;p>&lt;strong>0129. Sum Root to Leaf Numbers (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/advleetcode" target="_blank" rel="noopener"
>https://bit.ly/advleetcode&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/allleetcode" target="_blank" rel="noopener"
>https://bit.ly/allleetcode&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree containing digits from &lt;code>0-9&lt;/code> only, each root-to-leaf path could represent a number.&lt;/p>
&lt;p>An example is the root-to-leaf path &lt;code>1-&amp;gt;2-&amp;gt;3&lt;/code> which represents the number &lt;code>123&lt;/code>.&lt;/p>
&lt;p>Find the total sum of all root-to-leaf numbers.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> A leaf is a node with no children.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 25
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The root-to-leaf path 1-&amp;gt;2 represents the number 12.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The root-to-leaf path 1-&amp;gt;3 represents the number 13.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Therefore, sum = 12 + 13 = 25.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [4,9,0,5,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>5 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1026
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The root-to-leaf path 4-&amp;gt;9-&amp;gt;5 represents the number 495.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The root-to-leaf path 4-&amp;gt;9-&amp;gt;1 represents the number 491.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The root-to-leaf path 4-&amp;gt;0 represents the number 40.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Therefore, sum = 495 + 491 + 40 = 1026.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，當中只有數字0~9，&lt;br>
每個根到葉子的路徑可以表達一個數。&lt;br>
舉例來說，1-&amp;gt;2-&amp;gt;3可以表達123。&lt;br>
找出所有的根到葉的數字的總和。&lt;br>
(葉的定義是沒有子節點的節點)&lt;/p>
&lt;p>這題雖然標註為Medium，但其實並不那麼難思考，&lt;br>
只是定義要弄清楚而已。&lt;/p>
&lt;p>首先，假設我們在某個節點n，它如果左節點和右節點都沒有的話，&lt;br>
意味著它是葉(leaf)，這時數字就要計入總和；&lt;br>
如果有其中一個成立的話，我們應該要往下走，&lt;br>
並記錄之前經過的節點値，這樣子在遇到葉的時候才能夠結算。&lt;/p>
&lt;p>那麼自然，由於每棵樹只有0~9，&lt;br>
所以從一層樹到下一層的時候，原先經過的數字的作用會放大10倍。&lt;br>
也就是說，從上一層下來的時候，如果所在是葉的話，&lt;br>
我們應該要把這個數字&lt;strong>乘以10以後，加上現在的節點値&lt;/strong> 。&lt;/p>
&lt;p>因此，我們只要遍歷完整棵樹，&lt;strong>將葉子加總&lt;/strong> 起來即可。&lt;br>
寫成流程應該如下：&lt;/p>
&lt;ol>
&lt;li>檢查根節點是否為NIL，如果是，直接回傳0(此路不通)&lt;/li>
&lt;li>計算上面下來的值(last)到當前根節點的值(now)的結果，&lt;br>
&lt;strong>now = last * 10 + root.val&lt;/strong>&lt;/li>
&lt;li>如果左右節點均為NIL，直接回傳&lt;strong>now&lt;/strong> 即可(當前節點為葉)&lt;/li>
&lt;li>將&lt;strong>root.left, now及root.right, now&lt;/strong> 分別傳入做遞迴計算&lt;strong>左右子樹的和&lt;/strong> ，&lt;br>
最後&lt;strong>加總起來並回傳&lt;/strong> 。&lt;/li>
&lt;li>所以我們會先沿著最左邊一路到最底，然後依序將所有節點走過，&lt;br>
這樣子是先往深處走，所以是所謂的深度優先搜尋(DFS)的方法。&lt;/li>
&lt;/ol>
&lt;p>另外一方面，留意由於我們最開始已經檢查了root是否為NIL，&lt;br>
所以在傳入左右子節點時，可以讓前面這條檢查來確認NIL的狀況，&lt;br>
也就不用再先檢查節點是否為空了。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java可以使用相同的函式名稱，&lt;strong>傳入不同長度的參數&lt;/strong> 來處理。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/956fb2f701ae5495dea4e301a4b5fcd0.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，我們直接&lt;strong>設定預設值&lt;/strong> ，這樣就可以通用了XD&lt;br>
當從根節點開始時，由於只傳入root, 自然last會是0。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/bebba246f6dd601d4698ad348c08153c.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1), 如果算上call stack的部分的話，&lt;br>
平均空間複雜度是O(logN) (DFS的深度))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 97 Dynamic Programming (13)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-97-dynamic-programming-13/</link><pubDate>Wed, 17 Jun 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-97-dynamic-programming-13/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 97 Dynamic Programming (13)" />&lt;p>&lt;strong>0368. Largest Divisible Subset (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://bit.ly/2desolve" target="_blank" rel="noopener"
>https://bit.ly/2desolve&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://bit.ly/adesolve" target="_blank" rel="noopener"
>https://bit.ly/adesolve&lt;/a>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a set of &lt;strong>distinct&lt;/strong> positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies:&lt;/p>
&lt;p>Si % Sj = 0 or Sj % Si = 0.&lt;/p>
&lt;p>If there are multiple solutions, return any subset is fine.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,2] (of course, [1,3] will also be ok)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,4,8]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,2,4,8]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個內含不同正整數的集合，找出最大的子集合，使得當中任取一對元素(Si, Sj)出來均能符合Si整除Sj或Sj整除Si。&lt;br>
如果有多個不同的解，回傳當中任何一個都可以。&lt;/p>
&lt;p>首先我們可以先想到，在這個題目當中顯然nums是沒有被排序的，&lt;br>
如果以最笨的辦法來說的話，一個集合會擁有2^N個子集合&lt;br>
(因為每個元素都可以選擇要在這個子集合或不在這個子集合內)，&lt;br>
而每個組合當中如果又要兩兩檢查的話，又要各自花上n(n-1)/2的時間。&lt;br>
(n為該子集合的元素數量)&lt;br>
顯然直接考慮是非常不符合的，所以只好嘗試先排序過後，&lt;br>
看看能得到什麼可以用的特性。&lt;/p>
&lt;p>那在排序過後，我們會想到一個點是，如果我們由小到大看的話，&lt;br>
&lt;strong>假設前面選取了a跟b，那下一個選取的數c只需要確定能被b整除即可。&lt;/strong>&lt;br>
為什麼？因為按順序由小到大排，所以當我們選b的時候，&lt;br>
一定是要b能被a整除才行，於是後面接續的選擇，&lt;br>
只要確保能被最後一個數整除，就會符合能被前面的其他數整除了！&lt;/p>
&lt;p>接著下來，假設我們觀察一下數列的規律：&lt;br>
假設有一個數列是1, 2, 3, 4, 6, 8, 12, 18，&lt;br>
我們可以稍微列出幾串能成立Divisible Subset的內容&lt;br>
(先不考慮有沒有最大個數)：&lt;br>
&lt;strong>1, 2, 4&lt;/strong> , 8&lt;br>
&lt;strong>1, 3,&lt;/strong> 6, 12&lt;br>
1, 3, 6, &lt;strong>18&lt;/strong>&lt;br>
&lt;strong>1, 2&lt;/strong> , 6, 12&lt;br>
&lt;strong>1, 2,&lt;/strong> 6, 18&lt;/p>
&lt;p>有沒有發現，當中間選的不一樣，後面能接的數字也就不一樣，&lt;br>
&lt;strong>從最大的數字往回推的時候，上一個index就有可能因而改變。&lt;/strong>&lt;/p>
&lt;p>由於我們在考慮的是如何去找前面已經選取的子集合，&lt;br>
和下面要選取的數的關係，所以這基本上就是動態規劃的題目跑不了XD!&lt;/p>
&lt;p>那麼，該怎麼樣定這中間的關係呢？&lt;br>
首先選取我們的dp，這個值要能夠拿來比較哪個子集合是擁有最多元素的，&lt;br>
那我們不妨這麼定義：&lt;br>
&lt;strong>dp[i]就是從已經排序好的nums中，從index 0~i的數字中，&lt;br>
選取出來最大可整除的子集合其元素的個數，且這個子集合當中必須包含nums[i]。&lt;strong>為什麼要定義必須包含nums[i]呢？因為不管怎麼樣，&lt;br>
最起碼可以選取index i，這樣子我們就可以將所有&lt;/strong>dp[i]先初始化為1&lt;/strong> ，&lt;br>
因為這是它的保底。&lt;/p>
&lt;p>接下來，我們要怎麼去紀錄當確立一個子集合的時候，&lt;br>
整個子集合的長相呢？&lt;br>
可以利用每個比較大的數只需要看前面一個數是否能將其整除的特性，&lt;br>
定義一組陣列或串列，當中存放符合前面dp定義的時候，&lt;br>
nums[i]的&lt;strong>對應到前面一個數的index在哪裡&lt;/strong> ，&lt;br>
將其稱呼為lidx(last index)。我們在找到最大的解的時候，&lt;br>
後續可以利用lidx來列出整個解。因此，&lt;strong>將lidx全部初始化為-1&lt;/strong> ，&lt;br>
當我們最後迴圈找尋遇到-1的時候，就表示整個解都被我們列出來了。&lt;/p>
&lt;p>那接下來就簡單了，定義一個全局最大解所在的索引值max_idx，&lt;br>
以及最大解的元素總數max_dp，分別初始化成0跟1。&lt;br>
接下來我們需要一個雙層的迴圈，第一層迴圈是&lt;strong>i從0開始到nums尾端&lt;/strong> ，&lt;br>
以nums[i]做為當下這個子集合的最大值。&lt;br>
而第二層迴圈則是&lt;strong>j從i-1開始到0&lt;/strong> ，&lt;br>
目的是要一路往回找nums[i]是否整除nums[j]。&lt;br>
如果整除的話，代表有一個子集合的排列方式是：&lt;br>
&amp;hellip;&amp;hellip; , nums[j], nums[i]&lt;br>
這個子集合是不是對i來說是最好的狀況呢？&lt;br>
那就要看&lt;strong>dp[j]+1是不是比dp[i]還要大&lt;/strong> ，&lt;br>
如果比較大，才表示i的排列要換成走j這條線對吧XD？&lt;br>
所以&lt;strong>比較大&lt;/strong> 的話，我們就應該要&lt;strong>把dp[i]的值改成dp[j] + 1&lt;/strong> ，&lt;br>
並且&lt;strong>lidx[i]要改成j&lt;/strong> (因為改成走nums[j]這條路了)。&lt;br>
每次將j走完以後，dp[i]有可能被改變，&lt;br>
自然全局最大的解也有可能被改變，所以我們要檢查看看，&lt;br>
如果需要更動，就進行更動。&lt;/p>
&lt;p>如此完成了雙層迴圈後，&lt;br>
最後就&lt;strong>從max_idx開始以一個單層迴圈將解列出來&lt;/strong> ，&lt;br>
記得迴圈的&lt;strong>結束條件是index碰到-1&lt;/strong> (代表已經到頭了)。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，可以用Arrays.fill來進行填充初始值的動作，&lt;br>
其他則是使用ArrayList來將res一個一個加入(要用LinkedList也可以)。&lt;br>
最後一個for迴圈的部分，如果使用者不想留max_idx，&lt;br>
也可以直接使用while來操作，&lt;br>
每次的下一步則是&lt;strong>max_idx = lidx[max_idx]&lt;/strong> 。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/fdd2bb1e1469cff9ee02e721b9a71c09.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分則是用[x] * n的方式來初始化，其他的部分跟Java並無不同。&lt;br>
請留意將串列原地排要用&lt;strong>nums.sort()&lt;/strong> ，&lt;br>
如果用&lt;strong>sorted(nums)&lt;/strong> 的話則是會&lt;strong>回傳一個新的排序好的串列&lt;/strong> 。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/d6eb9b87f4c27cdd59a3e7a129c62fba.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N²)/O(N)，因為時間用到雙層迴圈，每層都是O(N)要相乘，&lt;br>
而O(N²)會大於排序用的O(NlogN)，所以就取O(N²)；&lt;br>
空間上則用到dp跟lidx，均為O(N))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，&lt;strong>「從Leetcode學演算法｜基礎篇」&lt;/strong> 已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然&lt;strong>整捆一起買總體比較划算&lt;/strong> (差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊：&lt;br>
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
>https://bit.ly/1desolve&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 96 BST (5) / DFS (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-96-bst-5-dfs-10/</link><pubDate>Tue, 09 Jun 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-96-bst-5-dfs-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 96 BST (5) / DFS (10)" />&lt;p>&lt;strong>1008. Construct Binary Search Tree from Preorder Traversal (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下，&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」在今天(6/9)中午12點&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友可以使用下面的早鳥優惠～&lt;br>
&lt;strong>「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong> ：&lt;br>
&lt;a class="link" href="https://hiskio.com/packages/YoRY45yZm" target="_blank" rel="noopener"
>https://hiskio.com/packages/YoRY45yZm&lt;/a>&lt;/p>
&lt;p>&lt;strong>「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;/strong>&lt;br>
&lt;a class="link" href="https://hiskio.com/packages/MByQ4pw3W" target="_blank" rel="noopener"
>https://hiskio.com/packages/MByQ4pw3W&lt;/a>&lt;/p>
&lt;p>另外，&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Return the root node of a binary &lt;strong>search&lt;/strong> tree that matches the given &lt;code>preorder&lt;/code> traversal.&lt;/p>
&lt;p>&lt;em>(Recall that a binary search tree is a binary tree where for every node, any descendant of&lt;/em> &lt;code>node.left&lt;/code> &lt;em>has a value&lt;/em> &lt;code>&amp;lt;``node.val&lt;/code>&lt;em>, and any descendant of&lt;/em> &lt;code>node.right&lt;/code> &lt;em>has a value&lt;/em> &lt;code>&amp;gt;``node.val&lt;/code>&lt;em>. Also recall that a preorder traversal displays the value of the&lt;/em> &lt;code>node&lt;/code> &lt;em>first, then traverses&lt;/em> &lt;code>node.left&lt;/code>&lt;em>, then traverses&lt;/em> &lt;code>node.right&lt;/code>&lt;em>.)&lt;/em>&lt;/p>
&lt;p>It’s guaranteed that for the given test cases there is always possible to find a binary search tree with the given requirements.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [8,5,1,7,10,12]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [8,5,10,1,7,null,12]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-96-bst-5-dfs-10/0_onS6QbVL4p9hvos1.png"
width="590"
height="386"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-96-bst-5-dfs-10/0_onS6QbVL4p9hvos1_hua11425f4769318de159e6ae8eeeb0176_21922_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-96-bst-5-dfs-10/0_onS6QbVL4p9hvos1_hua11425f4769318de159e6ae8eeeb0176_21922_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="152"
data-flex-basis="366px"
>&lt;/p>
&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= preorder.length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= preorder[i] &amp;lt;= 10^8&lt;/code>&lt;/li>
&lt;li>The values of &lt;code>preorder&lt;/code> are distinct.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>從給定的&lt;strong>前序走訪&lt;/strong> 一棵二元搜尋樹的結果，&lt;br>
重建一棵符合的二元搜尋樹，並回傳其根節點。&lt;br>
題目給出的測試資料均保證可以找到一個符合的二元搜尋樹。&lt;/p>
&lt;p>我們很早以前已經解說過&lt;strong>二元搜尋樹的特性&lt;/strong> 了，&lt;br>
&lt;strong>前序走訪(preorder)&lt;/strong> 表示順序是&lt;strong>根-左-右&lt;/strong> ，&lt;br>
不像是&lt;strong>中序走訪(inorder)&lt;/strong> 會剛好是&lt;strong>左-根-右，順序會剛好由小到大排列&lt;/strong> 。&lt;br>
那麼，我們要怎麼樣才能架構一個合理的BST(二元搜尋樹)呢？&lt;br>
由於BST和preorder的特性，當我們一路往左走的時候，&lt;br>
我們會&lt;strong>越走碰到的值越小&lt;/strong> ，這表示我們是一路看到&lt;strong>當下的根節點&lt;/strong> ，&lt;br>
接著往&lt;strong>左走看到左節點&lt;/strong> 才會發生這樣的狀況；&lt;/p>
&lt;p>如果我們當下碰到了比根節點還要大的狀況呢？&lt;br>
代表這段往左已經走完了，現在看到的是右節點。&lt;br>
那麼怎麼知道&lt;strong>是不是當下這個位置的右節點&lt;/strong> 呢？&lt;br>
我們必須要比較&lt;strong>現在所在的位置的前面的根節點值&lt;/strong> 才行。&lt;br>
如果比根節點值&lt;strong>小&lt;/strong> ，代表它是被包含在當下這個子二元樹，&lt;br>
反之，則代表它應該&lt;strong>在上一層或更上層&lt;/strong> 才對。&lt;br>
此外，我們可以設定一個class的變數i，&lt;br>
用來紀錄現在我們建立二元樹的過程走到哪個index。&lt;/p>
&lt;p>那麼我們來整理一下流程：&lt;br>
0. 初始化一個class變數 &lt;strong>i = 0&lt;/strong> 。&lt;/p>
&lt;ol>
&lt;li>先檢查當前的陣列/串列是不是&lt;strong>沒東西&lt;/strong> ，沒東西的話就回傳null/None。&lt;/li>
&lt;li>將&lt;strong>int的最大值&lt;/strong> 作為&lt;strong>邊界值&lt;/strong> bound，&lt;br>
傳入用來建立二元樹的函式(這裡命名為&lt;strong>build&lt;/strong> )&lt;/li>
&lt;li>在build函式中，檢查如果&lt;strong>i走完全長了&lt;/strong> 或者&lt;strong>preorder[i] &amp;gt; bound，&lt;br>
前者表示整個樹重建完了，後者表示這個子樹底下對於preorder[i]來說不可能放在任何一個地方了，所以回傳null/None回到上一層。&lt;strong>4. 在這層建立一個&lt;/strong> 根節點root&lt;/strong>，** 其值為preorder[i]&lt;strong>，完成後&lt;/strong> 將i遞增**。&lt;/li>
&lt;li>接下來要建立root.left，呼叫build函式，&lt;br>
將preorder&lt;strong>及邊界值root.val&lt;/strong> 傳入。&lt;br>
(因為root的左子樹所有值都要小於root的值)&lt;/li>
&lt;li>再來建立root.right，呼叫build函式，&lt;br>
將preorder及邊界值bound傳入。&lt;br>
(因為root的右子樹裡的所有值要介於&lt;strong>root的值&lt;/strong> 和&lt;strong>上一層限制的bound&lt;/strong> 之間)&lt;/li>
&lt;li>這層等於建立完畢了，&lt;strong>將root回傳&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>我們簡單拿Example 1為範例來嘗試推導看看：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>(i, preorder[i], bound) = (0, 8, Integer.MAX_VALUE)&lt;br>
=&amp;gt; root節點建立，其值為8，i遞增，呼叫build(preorder, 8)以建立左節點。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (1, 5, 8)&lt;br>
=&amp;gt; 建立根節點，其值為5，i遞增，呼叫build(preorder, 5)以建立左節點。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (2, 1, 5)&lt;br>
=&amp;gt; 建立根節點，其值為1，i遞增，呼叫build(preorder, 1)以建立左節點。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (3, 7, 1)&lt;br>
=&amp;gt; 7&amp;gt;1，所以表示這層沒辦法放了，回傳null到上一層。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (3, 7, 5)&lt;br>
=&amp;gt; 走到root.right這行，呼叫build(preorder, 8)以建立右節點。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (3, 7, 8)&lt;br>
=&amp;gt; 建立根節點，其值為7，i遞增，&lt;br>
呼叫root.left及root.right兩行都會回傳null，&lt;br>
所以回傳該節點到上一層。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (4, 10, 8)&lt;br>
=&amp;gt; 在5的底下建立完7的右節點了，這邊也完成了，&lt;br>
回傳5的節點回到上一層。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (4, 10, Integer.MAX_VALUE)&lt;br>
=&amp;gt; 走到root.right這行，呼叫build(preorder, Integer.MAX_VALUE)。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (4, 10, Integer.MAX_VALUE)&lt;br>
=&amp;gt; 建立根節點，其值為10，i遞增，&lt;br>
root.left這行會回傳null，&lt;br>
root.right傳入build(preorder, Integer.MAX_VALUE)。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>(i, preorder[i], bound) = (5, 12, Integer.MAX_VALUE)&lt;br>
=&amp;gt; 建立根節點，其值為12，i遞增。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>後面的部分由於i已經到達6，所以會往上層回到8的這層，&lt;br>
最後回傳根節點(值為8)，結束。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>請讀者嘗試在紙上畫出來推過一遍，有助於更了解整個程式運行。&lt;br>
由於我們是先一路往左深入並建立節點，碰到無法建立時，&lt;br>
才回到上一層並嘗試往右走，&lt;br>
所以這樣子的方式是&lt;strong>DFS(深度優先搜尋)&lt;/strong> 的模式。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，&lt;br>
使用int時可以用Integer.MAX_VALUE作為初始邊界(即int能表示的最大值)。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/39b4b56e6af4cda414fbe3fdc93fa9a3.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，我們可以設定bound在未傳入值時預設值當作&lt;strong>float(&amp;lsquo;inf&amp;rsquo;)&lt;/strong> ，&lt;br>
即可使用同一個函式進行遞迴。&lt;br>
此外，還是不要忘記Python並沒有++或&amp;ndash;，請自己換成用**”self.i += 1&amp;quot;** 。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/751f9e2e2f88ba60f6d45a2708341330.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(length of array)/O(1), 如果計算call stack的話則是O(BST的深度))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>另外，「從Leetcode學演算法｜基礎篇」已經回原價囉，&lt;br>
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br>
雖然整捆一起買總體比較划算(差290而已就有整組了阿XD)，&lt;br>
如果你還是想先試試基礎課的話，&lt;br>
&lt;strong>300元折抵的連結&lt;/strong> 在這邊： &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=NEXLJXE" target="_blank" rel="noopener"
>https://hiskio.com/courses/319?promo_code=NEXLJXE&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 95 Dynamic Programming (12)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-95-dynamic-programming-12/</link><pubDate>Sat, 06 Jun 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-95-dynamic-programming-12/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 95 Dynamic Programming (12)" />&lt;p>&lt;strong>1143. Longest Common Subsequence (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>容筆者工商一下，&lt;br>
接下來**「從Leetcode學演算法｜進階篇」** 即將於&lt;strong>6/9&lt;/strong> 開放預購啦！&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了面試準備須知分享，及訪談&lt;strong>國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;br>
有興趣的朋友請留意下一篇貼文的早鳥優惠～&lt;/p>
&lt;p>另外，&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two strings &lt;code>text1&lt;/code> and &lt;code>text2&lt;/code>, return the length of their longest common subsequence.&lt;/p>
&lt;p>A &lt;em>subsequence&lt;/em> of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, “ace” is a subsequence of “abcde” while “aec” is not). A &lt;em>common subsequence&lt;/em> of two strings is a subsequence that is common to both strings.&lt;/p>
&lt;p>If there is no common subsequence, return 0.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: text1 = &amp;#34;abcde&amp;#34;, text2 = &amp;#34;ace&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The longest common subsequence is &amp;#34;ace&amp;#34; and its length is 3.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: text1 = &amp;#34;abc&amp;#34;, text2 = &amp;#34;abc&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The longest common subsequence is &amp;#34;abc&amp;#34; and its length is 3.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: text1 = &amp;#34;abc&amp;#34;, text2 = &amp;#34;def&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There is no such common subsequence, so the result is 0.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= text1.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= text2.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>The input strings consist of lowercase English characters only.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個字串text1及text2，&lt;br>
回傳他們的最長共同子序列(Logest Common Subsequence, LCS)。&lt;br>
一個字串的子序列是指一個字串從字串中原始的一些字母得來，&lt;br>
當中刪去原字串的一些字元(也可以都不刪)，&lt;br>
但保持相對於在原字串中的排列順序。&lt;br>
&lt;strong>舉例來說&lt;/strong> ，&lt;strong>”ace&lt;/strong> ”是**”a** b&lt;strong>c&lt;/strong> d&lt;strong>e”&lt;/strong> 的子序列，但”a&lt;strong>e&lt;/strong> c”不是。&lt;br>
(排列相對順序已經不一樣了)&lt;br>
兩個字串的共同子序列是指這個字串分別都是兩個字串的子序列。&lt;/p>
&lt;p>如果沒有共同子序列，則回傳0。&lt;/p>
&lt;p>當我們看到題目乍看之下沒有明顯的簡單解法時，&lt;br>
就要考慮一下先找出&lt;strong>前後之間的關聯&lt;/strong> 。&lt;br>
也就是說，&lt;br>
我們要先考慮從某一步推往下一步的算式。&lt;/p>
&lt;p>由於我們要求的是LCS，這個要求對應順序的特性，&lt;br>
會導致一點：&lt;br>
&lt;strong>前面經過的字母，後面就不能用了。&lt;/strong> 比方說&amp;quot;&lt;strong>abec&lt;/strong> drr&amp;quot;跟”&lt;strong>ac&lt;/strong> e”，假設我們已經找到了 a 跟 c ，&lt;br>
接下來我們只會從”drr”跟”e”之間作找尋，&lt;br>
因為&amp;quot;abec&amp;quot;中的 e 沒辦法跟第二個字串對應(順序會亂掉)。&lt;br>
這也表示，分別對兩個字串取出兩個子字串的LCS，&lt;br>
&lt;strong>只會跟它們更前面的部分有關聯&lt;/strong> ，而和後面的字元沒有關係。&lt;br>
思考到這裡，顯然這極有可能是Dynamic Programming了XD&lt;/p>
&lt;p>那麼，我們不妨將t1和t2兩個子字串的記法用 i 和 j 表示，&lt;br>
當中0代表完全空字串，最大則分別到l1, l2。&lt;br>
(也就是i, j就代表現在在t1, t2的第幾個字元，&lt;strong>從1開始&lt;/strong> )&lt;br>
我們假設每個值互相關聯，那麼可以寫成一個二維陣列或串列dp。&lt;br>
所以我們知道dp[0][0] == dp[i][0] == dp[0][j] == 0。&lt;br>
(因為至少有一邊是空字串)&lt;br>
下一步呢？&lt;br>
如果我們在分別取 i, j 的字元數，那麼會分兩種狀況：&lt;br>
&lt;strong>1. t1[i-1] == t2[j-1] (i, j 的位置上的字元一模一樣)&lt;/strong>&lt;br>
=&amp;gt; &lt;strong>dp[i][j] = dp[i-1][j-1] + 1&lt;/strong> 因為對應的位置上得到相同字元，所以可以納入子序列中，&lt;br>
所以假設我們知道dp[i-1][j-1]，那麼dp[i][j]應該就恰好多1。&lt;/p>
&lt;p>*這邊很容易搞混，請留意因為計算 index 的時候是從&lt;strong>0&lt;/strong> 開始，&lt;br>
所以我們的&lt;strong>dp[i][j]&lt;/strong> 指的是比較 t1 的 &lt;strong>0 到 i-1&lt;/strong> 及 ** t2** 的 ** 0 到 j-1兩個子字串。**&lt;/p>
&lt;p>&lt;strong>2. i, j位置上的字元不同 =&amp;gt; 往回推一個字元&lt;br>
由於i, j上的字元不同，所以dp[i][j]要嘛和dp[i][j-1]相同，&lt;br>
要嘛和dp[i-1][j]相同。&lt;strong>也就是說，兩個子字串其中一個&lt;/strong> 往回退一格&lt;/strong>所得到的結果，&lt;br>
當中&lt;strong>取比較大&lt;/strong> 的就可以了。(因為我們在找最大的解嘛XD)&lt;/p>
&lt;p>為什麼不能同時退？&lt;br>
因為可能一邊對到的是前一個阿！&lt;br>
比方說：&lt;br>
“&lt;strong>a&lt;/strong> b&lt;strong>ce&lt;/strong> ffz”跟”&lt;strong>ac&lt;/strong> rrr&lt;strong>e”，&lt;/strong> 假設我們現在正在比較”abcef”跟”acrrre”，&lt;br>
由於f和e不一樣，所以我們要改成比較&amp;quot;abc&lt;strong>e&lt;/strong> &amp;ldquo;-”acrrr&lt;strong>e&lt;/strong> ”和”abce&lt;strong>f&lt;/strong> ”-”acrr&lt;strong>r&lt;/strong> ”。&lt;br>
如果我們直接各退一格，去比較”abce”跟&amp;quot;acrrr&amp;rdquo;，&lt;br>
那e的對應不就被我們去掉了嗎？所以顯然要去除掉沒有對應到的字元，&lt;br>
一次只能從其中一邊倒退一格才行。&lt;/p>
&lt;p>按照這個方式，我們可以使用雙層的迴圈，&lt;br>
就可以將整個dp陣列或串列算完，最終dp[l1][l2]就會是我們想要的答案。&lt;/p>
&lt;p>回顧一下，我們利用了&lt;strong>順序必須不變&lt;/strong> 的特性，&lt;br>
確定了某個位置的值&lt;strong>只跟前面的結果&lt;/strong> 有關；&lt;br>
接著，判定當下&lt;strong>對到的字元是否相同&lt;/strong> ，&lt;br>
&lt;strong>相同的話&lt;/strong> 可以計入並用&lt;strong>各自的前一格&lt;/strong> 的結果表示，&lt;br>
&lt;strong>不同的話&lt;/strong> 則要&lt;strong>看誰退一格比較好&lt;/strong> 。&lt;br>
因此所有的值彼此環環相扣，某個位置的值可以用前面的位置的值來表達，&lt;br>
所以這的確是&lt;strong>動態規劃&lt;/strong> 的問題無誤。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分除了要留意index的計算不要搞錯以外，&lt;br>
整個程式碼相當簡單。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/94081b4e07316ddde30b741fcbea6fb8.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分不要忘記二維串列不要連續用 * 的方式，&lt;br>
(記憶體使用會重疊而不是開新的串列，這個之前有提到過)&lt;br>
其他基本一模一樣。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/69e75a7085dbf609d186a1edf5967951.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(l1 * l2), O(l1 * l2))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>這題依照不同的起始方式，解也有不同的寫法，&lt;br>
讀者可以嘗試看看有沒有別的寫法。&lt;br>
同時，讀者可能會發現只要前一層的數據，&lt;br>
就可以拿來算下一層了，那麼，儲存的空間可以再進行精簡，&lt;br>
請想想看，這樣子空間複雜度會變成多少呢？&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經快回原價啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;/p>
&lt;p>想要一次全包的話，請等待下一篇貼文提供的&lt;strong>同捆包&lt;/strong> XD&lt;/p>
&lt;p>&lt;strong>如果不太確定這是不是你想要的，&lt;br>
底下是最後一波優惠連結(下次就回原價囉)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 94 Hash Table (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-94-hash-table-10/</link><pubDate>Sun, 24 May 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-94-hash-table-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 94 Hash Table (10)" />&lt;p>&lt;strong>0438. Find All Anagrams in a String (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string &lt;strong>s&lt;/strong> and a ** non-empty** string ** p**, find all the start indices of ** p**’s anagrams in ** s**.&lt;/p>
&lt;p>Strings consist of lowercase English letters only and the length of both strings &lt;strong>s&lt;/strong> and ** p** will not be larger than 20,100.&lt;/p>
&lt;p>The order of output does not matter.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>s: &amp;#34;cbaebabacd&amp;#34; p: &amp;#34;abc&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[0, 6]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The substring with start index = 0 is &amp;#34;cba&amp;#34;, which is an anagram of &amp;#34;abc&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The substring with start index = 6 is &amp;#34;bac&amp;#34;, which is an anagram of &amp;#34;abc&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>s: &amp;#34;abab&amp;#34; p: &amp;#34;ab&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[0, 1, 2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The substring with start index = 0 is &amp;#34;ab&amp;#34;, which is an anagram of &amp;#34;ab&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The substring with start index = 1 is &amp;#34;ba&amp;#34;, which is an anagram of &amp;#34;ab&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The substring with start index = 2 is &amp;#34;ab&amp;#34;, which is an anagram of &amp;#34;ab&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串s及一個非空的字串p，&lt;br>
試找出所有在p在s內的所有異位構詞(anagram)的起始的索引值。&lt;br>
本題當中的字串僅含小寫英文字母，且s和p的長度分別不會大於20, 100.&lt;br>
(但不用在意輸出的順序)&lt;/p>
&lt;p>我們先前已經提過anagram的定義了，詳情可見&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-41-hash-table-2-944fd5db94d" target="_blank" rel="noopener"
>&lt;strong>0242. Valid Anagram (Easy)&lt;/strong> &lt;/a>。簡單來說，anagram是指說兩個字串是由相同的字元組成的，&lt;br>
只有順序可能不同而已。&lt;/p>
&lt;p>我們先假設我們拿到兩個字串，要檢查它們是不是互為anagram，&lt;br>
端看它們的’a’出現的次數，’b’出現的次數，’c’出現的次數&amp;hellip;, &lt;br>
&amp;lsquo;z&amp;rsquo;出現的次數是否相同即可。&lt;br>
這個儲存兩者出現的次數，可以使用HashTable來計算，&lt;br>
而且由於我們要分的內容很簡單，所以只需要小寫字母個數26個即可，&lt;br>
也就是Java可以使用一個長度為26的一維陣列，&lt;br>
Python可以使用串列，要使用字典也行(相當於HashMap)。&lt;/p>
&lt;p>回到我們的問題，我們想要在s當中找到一個子字串，&lt;br>
使得這個子字串和p互為anagram，&lt;br>
這時候應該可以先將p的各字母出現次數先行記錄下來。&lt;br>
接下來&lt;strong>從s的index 0開始往右&lt;/strong> ，一路計算&lt;strong>走到可以取p的長度為止，&lt;br>
如果這段能和p的組成內容相同，那就可以記做其中一個解。&lt;/strong>&lt;/p>
&lt;p>為了要比對是否組成內容相同，&lt;br>
我們可以將每次看到的字母&lt;strong>從p的hash table中扣除掉&lt;/strong> ，&lt;br>
當所有整個hash table都歸零的時候，我們就知道當前的組成相同了。&lt;br>
但為了不需要每次都檢查整個hash table，&lt;br>
我們可以先行設定一個cnt變數，其值等於p的長度。&lt;br>
每次碰到可以扣除的組成就將cnt遞減，&lt;br>
&lt;strong>這樣當cnt為0且當前長度為和p長度相等時，就知道取得一個解了。&lt;/strong>&lt;/p>
&lt;p>接下來，我們需要一個left和一個right的索引值來記錄。&lt;br>
由於長度固定就這麼長，當我們已經來到左右距離p的長度時，&lt;br>
我們可以&lt;strong>將left和right各自往右移動一格&lt;/strong> 。&lt;br>
同時left移出&lt;/p>
&lt;p>舉例來說假設：&lt;br>
s: “e&lt;strong>cba&lt;/strong> eba&lt;strong>bac&lt;/strong> d” p: “abc” &lt;br>
(這邊將Example 1前面多加一個字元比較容易看出不同)&lt;/p>
&lt;ol>
&lt;li>(left, right, cnt) : (0, 0, 3) -&amp;gt; (0, 1, 3) -&amp;gt; (0, 2, 2) -&amp;gt; (0, 3, 1)&lt;br>
沿路會檢查&amp;rsquo;e&amp;rsquo;, &amp;lsquo;c&amp;rsquo;, &amp;lsquo;b&amp;rsquo;，每次碰到的字母會從p的hash table中扣掉，&lt;br>
不過cnt這樣只會降到1，表示&lt;strong>沒有成立anagram&lt;/strong> 。&lt;/li>
&lt;li>(left, right, cnt) : (0, 3, 1) -&amp;gt; (1, 4, 0)&lt;br>
將left往右移一格，’e’就出範圍外了(hash table要加回來)，&lt;br>
接著right往右移一格，’a’進入範圍內，且符合p的hash table擁有的子母，&lt;br>
&lt;strong>所以cnt會從1降為0，同時範圍長度相符，&lt;br>
表示這是其中一個解&lt;/strong>，將1加入到我們的答案範圍中。&lt;/li>
&lt;li>(left, right, cnt) : (1, 4, 0) -&amp;gt; (2, 5, 1) -&amp;gt; (3, 6, 2) -&amp;gt; (4, 7, 3)&lt;br>
依序移出範圍，&lt;strong>如果發現加上去前hash table該值有≥0的話，&lt;br>
表示有移出p原有的字母，所以我們要將cnt進行遞增&lt;/strong>。&lt;/li>
&lt;li>(left, right, cnt) : (4, 7, 3) -&amp;gt; (5, 8, 2) -&amp;gt; (6, 9, 1) -&amp;gt; (7, 10, 0)&lt;br>
同樣經歷了一個cnt等於0且長度等於p的範圍，&lt;br>
將&lt;strong>7&lt;/strong> 加入答案當中。&lt;/li>
&lt;li>(left, right, cnt) : (8, 11, 1) -&amp;gt; right超過，停止檢查。&lt;/li>
&lt;/ol>
&lt;p>所以按上面這個範例的output就會是[1, 7]。&lt;/p>
&lt;p>這個題目由於我們中途開始的left和right呈現一個固定距離的狀態，&lt;br>
只是隨著遞增&lt;strong>滑動&lt;/strong> ，所以這種固定窗口大小並且移動的方式，&lt;br>
一般稱為&lt;strong>Sliding Window&lt;/strong> 。&lt;br>
(也可以視為Two Pointer在某種狀態的條件限定)&lt;/p>
&lt;p>依此，我們可以寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，參考了一位leetcode上的解法，&lt;br>
我們使用一個ArrayList來儲存我們的答案，&lt;br>
並且前期的檢查可以分別檢查s, p是否為null或空，&lt;br>
以及s的長度不能小於p的長度才行(不然要怎麼組對吧XD)&lt;/p>
&lt;p>接著，我們使用一個長度26的一維陣列，&lt;br>
也可以使用ASCII長度256直接存，我們使用26的長度時，&lt;br>
index使用c-’a’即可對應。&lt;/p>
&lt;p>初始化left, right, count後，迴圈條件設定為right還沒有超出去範圍。&lt;br>
迴圈內的判斷式則利用++和&amp;ndash;的特性，&lt;br>
(放後面時會先進行完整個操作才遞增/遞減)，&lt;br>
其他的重點做法跟前面的描述是一樣的，&lt;br>
讀者可以再自己嘗試在紙上推導一次，會更加清楚。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/4f0f9cb395c0e50c50c1e8c1663c3669.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分我們示範使用字典來處理，&lt;br>
由於我們不想要每次在取值時都先檢查值有沒有存在的問題，&lt;br>
(不論是get或者是用[]取值，字典都不會有預設值)&lt;br>
&lt;strong>所以這邊先行將26個字母的對應都置入0，後續就不需要再檢查了。&lt;/strong> 其它的部分跟Java的寫法基本相同，只是沒有++跟- -能用而已XD!&lt;/p>
&lt;script src="https://gist.github.com/Desolve/843bd02ae84e41fa25f51d938e2ddd3b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，&lt;br>
空間複雜度如果要算上答案的部分的話則為O(N)，N為s的長度)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 93 Tree (12) / DFS (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-93-tree-12-dfs-9/</link><pubDate>Sun, 10 May 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-93-tree-12-dfs-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 93 Tree (12) / DFS (9)" />&lt;p>&lt;strong>0687. Longest Univalue Path (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>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>
&lt;p>The length of the path between two nodes is represented by the number of edges between them.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;strong>Input:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 1 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Output:&lt;/strong> 2&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;strong>Input:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 4 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Output:&lt;/strong> 2&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> The given binary tree has not more than 10000 nodes. The height of the tree is not more than 1000.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，尋找其最長的路徑長，&lt;br>
當中的所有節點必須擁有相同的值。&lt;br>
這條路徑通過或沒有通過根節點均可。&lt;br>
(路徑長度的定義為兩個節點之間經過的邊(edge)的數量)&lt;/p>
&lt;p>由於很早我們就介紹過樹的基本性質了，&lt;br>
(印象模糊的讀者請回頭參照&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"
>0100. Same Tree&lt;/a>)，&lt;br>
在此就不再贅述。這題嘗試要找相同值的路徑，&lt;br>
但又不限定要通過root，該怎麼思考呢？&lt;br>
我們可以先考慮怎樣可以算&lt;strong>一條相同值的路徑&lt;/strong> 。&lt;br>
一條相同值的路徑有可能有以下兩種狀況：&lt;/p>
&lt;ol>
&lt;li>從一個頂點下來，&lt;br>
每次選擇往左節點走或往右節點走，到一個位置停下。&lt;br>
例如：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 1 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當中的5-5-5就是一條相同值的路徑。&lt;/p>
&lt;ol start="2">
&lt;li>從一個頂點進行分岔，左右各自走到一個位置停下。&lt;br>
例如：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>　　　4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 4 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當中的&lt;strong>粗斜體的4-4-4&lt;/strong> 就是一條從頂點往左右分岔所得到的路徑，&lt;br>
可以選擇從&lt;strong>左下的4 -&amp;gt; 中間的4 -&amp;gt; 再到右邊的4&lt;/strong> ，這樣連成一個路徑。&lt;br>
但從這邊來看可以發現，這條路徑就無法把root的4算在內，&lt;br>
&lt;strong>因為不管怎麼連，我們都沒辦法一筆不重複將這4個4走完。&lt;/strong>&lt;/p>
&lt;p>因此，我們可以得知：&lt;br>
對於某個節點來說，有經過它所能得到的最長路徑，&lt;br>
有可能是從&lt;strong>它的上面連下來(分岔點在它的上面&lt;/strong> )，&lt;br>
也可能是&lt;strong>以它自己為分岔點&lt;/strong> ，左右各自找完和它值相同的節點路徑。&lt;br>
在第一個情況來說，&lt;strong>要求它的上一個節點值和它的值相同；&lt;/strong>&lt;br>
第二個情況來說，則要將&lt;strong>左右和它的值相同的路徑長相加&lt;/strong> 。&lt;/p>
&lt;p>所以我們可以定義一個count函式，&lt;br>
回傳以某個節點值來說，其下的最長所能得到的相同值的路徑長，&lt;br>
當中計算的時候一邊留意當下最長的路徑長並進行更新。&lt;/p>
&lt;p>我們將整個題目的答案(相同值的最長路徑長)叫做mx(叫result也可以)，&lt;br>
&lt;strong>流程順序應為：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>一開始應該先&lt;strong>檢查root是否為NIL&lt;/strong> ，&lt;br>
如是，回傳&lt;strong>0&lt;/strong> (因為沒有路徑)，否則呼叫count函式，&lt;br>
&lt;strong>檢查它所能得到的相同值的最長路徑長&lt;/strong> 。&lt;br>
(傳入root節點，及當下的&lt;strong>路徑節點值root.val&lt;/strong> )&lt;/li>
&lt;li>在count當中，&lt;br>
同樣應先檢查傳入的節點值是否為null，&lt;br>
接下來為了要知道左右路徑的相同值的最長路徑長，&lt;br>
應該要分別帶入其&lt;strong>left/right節點及當前節點的值&lt;/strong> 進去檢查，&lt;br>
假設得到的結果分別為&lt;strong>l/r&lt;/strong> 。&lt;/li>
&lt;li>依照2的定義，l + r的值代表了一條可能的相同值路徑，&lt;br>
所以要拿它和mx比較，將較長的路徑值更新。&lt;/li>
&lt;li>如果&lt;strong>當前的節點值&lt;/strong> 和**傳進來的路徑節點值兩者相同，&lt;br>
代表有機會可以考慮上面提到過的&lt;br>
「&lt;strong>從一個頂點下來，每次選擇往左節點走或往右節點走，&lt;br>
到一個位置停下。&lt;/strong>」的狀況，&lt;br>
這時候要回傳的值會是左右路徑長較長的部分+1。&lt;br>
(因為要包含左節點/右節點到當前節點的這個路徑)&lt;/li>
&lt;li>上面的判斷不成立的話，代表路徑從上面下來到這邊斷掉了。&lt;br>
(值不相同)，這時候應該回傳0，代表相同值路徑到這邊沒辦法繼續。**&lt;/li>
&lt;/ol>
&lt;p>上面的流程順序，請讀者務必自行畫圖推導，&lt;br>
會比較清楚整個思考過程。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分mx直接宣告一個class變數即可，其它就是使用Math.max，&lt;br>
及檢查null的部分，並不複雜。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/08af5452682a0112c7484b118310a12e.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的話，可以使用self.mx來宣告，&lt;br>
並且在__init__時進行處理，&lt;br>
其它就是一樣注意呼叫時不要忘記用&lt;strong>self&lt;/strong> 即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/2de59e38d37647b769952cc56f3fa375.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，如果空間要算上call stack的部分的話，&lt;br>
則是O(TreeNode的高度)。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 92 String (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-92-string-5/</link><pubDate>Sun, 03 May 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-92-string-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 92 String (5)" />&lt;p>&lt;strong>0680. Valid Palindrome II (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a non-empty string &lt;code>s&lt;/code>, you may delete &lt;strong>at most&lt;/strong> one character. Judge whether you can make it a palindrome.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;aba&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: True
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;abca&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: True
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: You could delete the character &amp;#39;c&amp;#39;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>The string will only contain lowercase characters a-z. The maximum length of the string is 50000.&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個非空白的字串s，最多可以從當中刪除掉一個字元，&lt;br>
試判斷你能否讓這個字串變成一個回文。&lt;/p>
&lt;p>回文(Palindrome)先前已經&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-74-linked-list-8-27c4894da297" target="_blank" rel="noopener"
>&lt;strong>介紹過了&lt;/strong> &lt;/a>，&lt;br>
就是符合「從尾到頭和從頭到尾看起來相同」即可，&lt;br>
所以它可以是像是&lt;strong>abcba&lt;/strong> 的形式(中間有一個單獨的字元)，&lt;br>
或者是&lt;strong>abba&lt;/strong> (成對兩兩相對)，這個概念在很多回文的題目都有用到，&lt;br>
讀者可以多加留意。&lt;/p>
&lt;p>假設今天不能刪除任何字元的話，&lt;br>
問題就會直接變成檢查字串是否是回文，&lt;br>
那麼我們就可以直接設定兩個index i, j，&lt;br>
當中&lt;strong>i從0開始遞增，j從s.length()-1(或len(s)-1)開始遞減&lt;/strong> ，&lt;br>
&lt;strong>依序對照對稱的位置檢查字元是否相等&lt;/strong> 即可。&lt;br>
(檢查到i, j交會都還兩兩對稱相等，則為回文)&lt;/p>
&lt;p>好，那麼問題來了：&lt;br>
如果原先不是回文，需要刪掉一個字元才能變成回文呢？&lt;br>
該刪哪個？&lt;br>
有一句話說得好：&lt;br>
「解決不了問題，就解決產生問題的人」(大誤)，&lt;br>
既然我們只有一個可以刪的空間，&lt;br>
那麼就只能等到有無法對應到的狀況才處理。&lt;br>
舉例來說：&lt;br>
abcc&lt;strong>e&lt;/strong> ba -&amp;gt; a-a, b-b, 在c-e這個地方沒有對應到，&lt;br>
那麼有可能是c有問題，也有可能是e有問題，&lt;br>
所以我們可以分成刪掉c或刪掉e的狀況來檢查。&lt;br>
(因為實際上我們不會預先知道是誰有問題，也有可能都有問題)&lt;br>
也就是說，&lt;br>
當i, j沒辦法對應到時，我們可以選擇&lt;strong>略過i&lt;/strong> 的位置上的字元，&lt;br>
或者&lt;strong>略過j&lt;/strong> 的位置上的字元。(因為只是要檢查，所以不用真的作刪除)&lt;br>
&lt;strong>略過i&lt;/strong> 的話，我們就要嘗試拿&lt;strong>i+1來和j做對應&lt;/strong> ；&lt;br>
&lt;strong>略過j&lt;/strong> 的話，則是拿&lt;strong>i和j-1做對應&lt;/strong> 。&lt;br>
剩下的狀況，就是按照前面一般檢查回文的流程依序檢查，&lt;br>
只要這兩條路&lt;strong>其中一種&lt;/strong> 可以讓s變為回文，答案就會是&lt;strong>true&lt;/strong> 。&lt;br>
那麼，如果又碰到沒對應到的呢？&lt;/p>
&lt;p>那我們就只能說抱歉了XD~&lt;br>
我們已經用掉了一次刪除的機會，&lt;br>
後面再碰到對應不上的，當然就是不能成為回文囉！&lt;br>
所以這題看似會產生分支，其實只會產生一次而已，&lt;br>
因為我們只能刪一次而已，所以這題的時間複雜度並不高。&lt;/p>
&lt;p>依此，我們寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9651f4de798ee3f0de7483dfa602687f.js">&lt;/script>
&lt;p>Java的部分求方便起見，使用了toCharArray()，&lt;br>
我們將後續略過1個字元檢查的函式稱為isp(isPalindrome)，&lt;br>
當validPalindrome內的迴圈檢查到不符合的時候，&lt;br>
便呼叫isp來分支檢查；進入isp時，則只有所有剩下的字元兩兩對應，&lt;br>
才會回傳true，否則一定會回傳false。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/5e6a346fd0f59d8135ef0d84b4abff17.js">&lt;/script>
&lt;p>Python的部分，一樣不要忘記被用到的子函式要先宣告在前面，&lt;br>
其它和Java的解大同小異。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(len(s))/O(1)，&lt;br>
由於最多分支就只有一次，&lt;br>
所以總體的複雜度還是跟字串長有關；&lt;br>
Java的部分因為偷懶使用toCharArray()，&lt;br>
所以空間複雜度也是O(len(s))，願意節省一點的話，&lt;br>
也可以用CharAt()來取得某個位置的字元。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 91 String (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-91-string-4/</link><pubDate>Sun, 19 Apr 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-91-string-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 91 String (4)" />&lt;p>&lt;strong>0678. Valid Parenthesis String (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string containing only three types of characters: ‘(‘, ‘)’ and ‘*’, write a function to check whether this string is valid. We define the validity of a string by these rules:&lt;/p>
&lt;ol>
&lt;li>Any left parenthesis &lt;code>'('&lt;/code> must have a corresponding right parenthesis &lt;code>')'&lt;/code>.&lt;/li>
&lt;li>Any right parenthesis &lt;code>')'&lt;/code> must have a corresponding left parenthesis &lt;code>'('&lt;/code>.&lt;/li>
&lt;li>Left parenthesis &lt;code>'('&lt;/code> must go before the corresponding right parenthesis &lt;code>')'&lt;/code>.&lt;/li>
&lt;li>&lt;code>'*'&lt;/code> could be treated as a single right parenthesis &lt;code>')'&lt;/code> or a single left parenthesis &lt;code>'('&lt;/code> or an empty string.&lt;/li>
&lt;li>An empty string is also valid.&lt;/li>
&lt;/ol>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;()&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: True
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;(*)&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: True
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;(*))&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: True
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong> The string size will be in the range [1, 100].&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串，當中僅含三種字元：&amp;rsquo;(&amp;rsquo;, ‘)’, ‘*’ (左括號，右括號及米字號)，試寫一個函式以檢查這個字串是否有效。&lt;br>
一個字串要符合以下的規則才算是有效的：&lt;/p>
&lt;ol>
&lt;li>任一個左括號都要有一個對應的右括號&lt;/li>
&lt;li>任一個右括號都要有一個對應的左括號&lt;/li>
&lt;li>左括號必須出現在其對應的右括號之前&lt;/li>
&lt;li>米字號(*)可以被視為單一個右括號、左括號、或空字串&lt;/li>
&lt;li>空字串也是有效的&lt;/li>
&lt;/ol>
&lt;p>綜合上面的描述，我們可以知道像是：&lt;br>
‘)(’ -&amp;gt; 右括號還沒對應就出現在左括號前所以是False；&lt;br>
但像是‘(()()*)’ 就會是True，&lt;br>
仔細觀察可以發現，如果我們先不考慮米字號的部分，&lt;br>
&lt;strong>從左到右，左括號出現的次數必然 &amp;gt;= 右括號出現的次數。&lt;br>
(因為要兩兩相對應，且右括號不能還沒對應到就出現在左括號之前)&lt;/strong>&lt;/p>
&lt;p>所以，如果是沒有米字號的話，這題會相當簡單：&lt;br>
定義一個cnt(初始值為0)，由左至右，&lt;br>
每次&lt;strong>碰到左括號則+1，右括號則-1&lt;/strong> ，中間如果cnt變為&lt;strong>負數&lt;/strong> ，&lt;br>
則代表&lt;strong>有右括號還沒對應到就出現了&lt;/strong> ，則有效性是&lt;strong>False&lt;/strong> ；&lt;br>
而遍歷整個字串到結尾時，&lt;br>
如果&lt;strong>cnt變為0&lt;/strong> 的話則有效性是&lt;strong>True&lt;/strong> (剛好所有括號兩兩對應)，&lt;br>
否則則為&lt;strong>False&lt;/strong> (還有未對應到的括號)。&lt;/p>
&lt;p>那麼，加上米字號的話該怎麼辦呢？&lt;br>
我們可以先&lt;strong>將所有的米字號當成左括號來用&lt;/strong> ，&lt;br>
由左至右檢查是否左括號足夠配對右括號完還有剩。&lt;br>
假設&lt;strong>中途左括號不夠的話&lt;/strong> ，肯定是&lt;strong>False&lt;/strong> (因為加上米字號都不夠用)；&lt;br>
&lt;strong>配對完剛好用完&lt;/strong> -&amp;gt; ** True**(因為所有的米字號全拿來當左括號剛好OK)&lt;br>
配對完&lt;strong>左括號還有剩&lt;/strong> 呢？&lt;br>
這時候我們應該&lt;strong>從右至左，&lt;/strong> 換成將&lt;strong>所有的米字號當成右括號來用，&lt;br>
換成檢查右括號足不足夠配對。&lt;br>
中途右括號不夠 -&amp;gt; False；&lt;br>
最後如果右括號數量足夠的話，則為True。&lt;/strong>&lt;/p>
&lt;p>最後一段我們需要更仔細的考慮原因：&lt;br>
有沒有可能在由左至右留下來多出來的部分是左括號呢？&lt;br>
答案是否定的，因為如果是這樣的話，這些多出來的部分，&lt;br>
在反方向的時候會因為它們不是米字號，使得&lt;strong>右括號的數量不夠用&lt;/strong> ，&lt;br>
從而讓&lt;strong>中途不足以配對&lt;/strong> 的狀況發生。&lt;br>
所以要嘛就是&lt;strong>剛好完全配對&lt;/strong> ，不然的話，就是&lt;strong>剩下的全都是米字號&lt;/strong> ，&lt;br>
這樣反向時才有辦法處理。&lt;/p>
&lt;p>所以，當雙向都能夠順利滿足的時候，&lt;br>
只要將多出來的米字號視作空字串，就能使整個字串得以滿足有效性了！&lt;/p>
&lt;p>依照上面的邏輯，我們可以進行 two pass 經過整個字串，&lt;br>
完成整個檢查工作，其空間複雜度為O(1)，時間複雜度為O(n)。&lt;br>
(n為字串的長度)&lt;/p>
&lt;p>寫成程式碼如下。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，使用charAt()來取得特定index的字元，&lt;br>
並分別設定l跟r變數來計算。(要設成同一個cnt變數也行，自己歸零即可)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/b56b4a7c4847de705aa2b37a7173e5bd.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，這邊使用三元運算子處理。&lt;br>
此外，如果不想用index一個一個數的話，&lt;br>
用for c in s以及for c in reversed(s)也可以。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/86b1232ac8258f63c1e8f84b171f8da4.js">&lt;/script>
&lt;p>讀者可能會留意到註解裡有附註了&lt;a class="link" href="https://leetcode.com/problems/valid-parenthesis-string/discuss/107570/JavaC%2B%2BPython-One-Pass-Count-the-Open-Parenthesis" target="_blank" rel="noopener"
>&lt;strong>lee215的one pass解法&lt;/strong> &lt;/a>，&lt;br>
有興趣的可以再深入了解。具體的思路是記錄從左至右途中，&lt;br>
我們現在需要等待多少右括號來將一組括號完整；&lt;br>
&lt;strong>cmax&lt;/strong> 是&lt;strong>將所有碰到的*都當作是左括號&lt;/strong> 處理，&lt;br>
(也就是最大&lt;strong>可能&lt;/strong> 會產生尚未配對的左括號數量)&lt;br>
而&lt;strong>cmin&lt;/strong> 是&lt;strong>中間能消去配對的狀況就消去&lt;/strong> 。&lt;br>
(也就是最少&lt;strong>一定&lt;/strong> 要被配對完成的左括號數量)&lt;br>
按這個條件的話，cmax必然要一直&amp;gt;=0，&lt;br>
且cmin再結尾時要剛好是0才可以。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n)/O(1)，n為字串長度，空間不論是哪種方式都只需常數大小)&lt;/p>
&lt;p>「如果不管空間複雜度，你能使用stack來解這題嗎？」&lt;br>
(可以做配對然後將成對的括號吐掉，&lt;br>
具體可以參考以下幾個discussion的解法。&lt;br>
Java: &lt;a class="link" href="https://leetcode.com/problems/valid-parenthesis-string/discuss/107572/Java-using-2-stacks.-O%28n%29-space-and-time-complexity." target="_blank" rel="noopener"
>https://leetcode.com/problems/valid-parenthesis-string/discuss/107572/Java-using-2-stacks.-O(n)-space-and-time-complexity.&lt;/a>&lt;/p>
&lt;p>Python: &lt;a class="link" href="https://leetcode.com/problems/valid-parenthesis-string/discuss/145228/python-using-stack-20ms-beats-100-probably-the-easiest-solution" target="_blank" rel="noopener"
>https://leetcode.com/problems/valid-parenthesis-string/discuss/145228/python-using-stack-20ms-beats-100-probably-the-easiest-solution&lt;/a>)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 90 Dynamic Programming (11) / DFS (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/</link><pubDate>Sun, 22 Mar 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 90 Dynamic Programming (11) / DFS (9)" />&lt;p>&lt;strong>0576. Out of Boundary Paths (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>There is an &lt;strong>m&lt;/strong> by ** n** grid with a ball. Given the start coordinate ** (i,j)** of the ball, you can move the ball to an ** adjacent** cell or cross the grid boundary in four directions (up, down, left, right). However, you can ** at most** move ** N** times. Find out the number of paths to move the ball out of the grid boundary. The answer may be very large, return it after mod 10⁹ + 7.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: m = 2, n = 2, N = 2, i = 0, j = 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-001.png"
width="800"
height="473"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-001_hu0e08e66dd714ede57481fcf101c560c2_74568_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-001_hu0e08e66dd714ede57481fcf101c560c2_74568_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="169"
data-flex-basis="405px"
>&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: m = 1, n = 3, N = 3, i = 0, j = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-002.png"
width="756"
height="443"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-002_huaab6cb72f00c1390a11314959bcbbce1_51532_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-90-dynamic-programming-11-dfs-9/image-002_huaab6cb72f00c1390a11314959bcbbce1_51532_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="170"
data-flex-basis="409px"
>&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Once you move the ball out of the boundary, you cannot move it back.&lt;/li>
&lt;li>The length and height of the grid are in the range [1,50].&lt;/li>
&lt;li>N is in range [0,50].&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目描述有一組 m * n 的方格，格子上有一個球，其起始座標為 (i, j)，&lt;br>
你可以將球移到四個方向內沒超過邊界的格子，但最多只能移動N次。&lt;br>
試算出所有會將球移超過邊界的路徑數目。&lt;br>
限制：&lt;/p>
&lt;ol>
&lt;li>一旦移出邊界就不能再回來(也就是直接遊戲結束了)&lt;/li>
&lt;li>格子的寬高均在1~50的範圍&lt;/li>
&lt;li>總次數N在0~50的範圍&lt;br>
另由於答案可能非常大，回傳結果要先&lt;strong>除以10的9次方+7。&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>我們先思考關於路徑超過邊界的狀態。&lt;br>
要被算做是其中一種的話，首先最後一步一定要是從&lt;strong>格子內移到格子外&lt;/strong> ，&lt;br>
也就是要在邊界才可以，只差一格index就&lt;strong>小於0&lt;/strong> 或**&amp;gt;m-1** (或&lt;strong>n-1&lt;/strong> )。&lt;br>
畢竟不在懸崖邊怎麼可能會有掉下懸崖的可能對吧XD！&lt;br>
並且，因為&lt;strong>掉下去就回不來了&lt;/strong> ，所以路徑就會到此為止。&lt;br>
(當然不管剩下的步數，你總不會飛簷走壁吧@@)&lt;/p>
&lt;p>接著，當 &lt;strong>N=0&lt;/strong> 時，&lt;br>
&lt;strong>由於根本沒辦法動，自然不會有符合的路徑&lt;/strong> ，答案為0。&lt;br>
&lt;strong>N = 1&lt;/strong> 時，則要** 看你四邊有幾個懸崖&lt;strong>對吧！&lt;br>
那N = 2呢？&lt;br>
是不是就要先看&lt;/strong>這一步有幾種可能會掉下去，加總起來以後** ，&lt;br>
接下來&lt;strong>先走到不會掉下去的地方，再看那幾個有幾種情況會掉下去。&lt;br>
由於每走一步路，可用的步數就會少1&lt;/strong>，&lt;br>
我們終究會&lt;strong>要嘛掉下去&lt;/strong> ，&lt;strong>要嘛走到沒有步數可用；&lt;/strong>&lt;br>
將所有加總起來，就得到答案了。&lt;/p>
&lt;p>這個方式聽起來很DFS對吧？&lt;br>
所以按照上面的直覺，也許你會寫成像這樣子的內容：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span># Will TLE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>class Solution:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> def findPaths(self, m: int, n: int, N: int, i: int, j: int) -&amp;gt; int:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> def dfs(i, j, N):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res = 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if N != 0:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res += 1 if i - 1 &amp;lt; 0 else dfs(i-1, j, N-1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res += 1 if i + 1 == m else dfs(i+1, j, N-1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res += 1 if j - 1 &amp;lt; 0 else dfs(i, j-1, N-1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res += 1 if j + 1 == n else dfs(i, j+1, N-1)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return res
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res = dfs(i, j, N)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return res % (10 ** 9 + 7)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當方向會掉下去的時候，就代表方法數加1；&lt;br>
否則的話，就要往那個方向走1步去算可能的方法。&lt;br>
你會發現測試一般的結果可以算出正確答案，&lt;br>
但大一點的數字會算到超時，為什麼呢？&lt;/p>
&lt;p>其實理由跟以前我們算Fibonacci數列時一樣，&lt;br>
這樣子的寫法會導致每一個數都是從單一個1累加起來的，&lt;br>
中間我們可能走到同樣的格子，剩下相同的步數，&lt;br>
卻沒有利用到這點，從而導致效率超級差。&lt;/p>
&lt;p>那怎麼辦呢？&lt;br>
當我們同時考慮動態規劃的觀念時，&lt;br>
就容易想到，我們可以將先前算過的東西當成已知的內容儲存起來，&lt;br>
當再碰到時，就可以直接取用計算。&lt;br>
在本例當中，影響到結果的值有i, j, N，&lt;br>
所以我們可以選擇使用&lt;strong>一個三維的陣列/串列&lt;/strong> ，(也可以用兩個二維陣列)&lt;br>
或者Python內也可以用&lt;strong>字典&lt;/strong> 來做對應儲存。&lt;br>
扣除掉這點以外，跟前面的寫法並無不同，讀者可以自行參照看看。&lt;/p>
&lt;p>那麼，有沒有別種思考的方式呢？&lt;br>
有的，像是lee215就提供了另一種思路：&lt;br>
我們最開始N=0時，整個盤面不論i, j為什麼，&lt;br>
(i, j, 0)的結果都會是0，而(i, j, N)的結果，&lt;br>
則取決於**(i, j)上下左右4格在N-1步的時候** 的結果。&lt;br>
如果該格超出邊界，則至少從(i, j)有1步可以走出邊界，&lt;br>
反之，(i, j)可以花1步走過去。&lt;br>
因此，我們可以一次一次更新整個盤面，&lt;br>
從而算得第N步的結果。(&lt;strong>參見Python lee215解&lt;/strong> )&lt;/p>
&lt;p>或者，我們也可以從i, j為起點，&lt;br>
記錄從&lt;strong>i, j到某一格的總路徑數量&lt;/strong> ，&lt;br>
&lt;strong>每當有機會超出邊界時，則將該部分加總到結果中，&lt;br>
兩個方法殊途同歸，最後都可以得到解答。(參見Java shawngao解)&lt;/strong>&lt;/p>
&lt;p>依照上面的這些想法，我們可以寫成解答：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>在Java的部分，除了上面提過的遞進計算整個盤面，&lt;br>
(使用兩個二維陣列交替)&lt;br>
也可以用三維陣列去記錄結果，&lt;br>
留意為了要偵測是否有記錄結果，&lt;br>
我們要用Arrays.fill()，將初始化的陣列都填入-1，&lt;br>
這樣我們才知道這個值它是0還是未填入的狀態。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/0f38d843a1cec840a22f7c2b6855078e.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，除了lee215的解法外，&lt;br>
我們也可以如上面提到的採用一個字典來進行儲存先前已計算過的內容。&lt;br>
此外，由於在這個問題中，&lt;br>
鏡像對稱位置的點在相同的N值下應該會有相同的答案，&lt;br>
所以還可以透過對稱的方式來進一步化簡所需的計算數量。&lt;br>
(可以看註解底下最後一個解，65~69行的部分)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/c116a47b873399929e841da0e7b405b3.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(時間複雜度方面，原則上最壞的狀況就是每個步驟算完整個盤面，&lt;br>
所以會是&lt;strong>O(m*n*N)&lt;/strong> 。&lt;br>
空間複雜度的話，使用&lt;strong>三維陣列或字典&lt;/strong> 的話是&lt;strong>O(m*n*N)&lt;/strong> ，&lt;br>
而使用&lt;strong>兩個二維陣列交替記錄&lt;/strong> 的話則是&lt;strong>O(m*n)&lt;/strong> )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 89 Hash Table (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-89-hash-table-9/</link><pubDate>Sun, 01 Mar 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-89-hash-table-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 89 Hash Table (9)" />&lt;p>&lt;strong>1346. Check If N and Its Double Exist (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array &lt;code>arr&lt;/code> of integers, check if there exist two integers &lt;code>N&lt;/code> and &lt;code>M&lt;/code> such that &lt;code>N&lt;/code> is the double of &lt;code>M&lt;/code> ( i.e. &lt;code>N = 2 * M&lt;/code>).&lt;/p>
&lt;p>More formally check if there exist two indices &lt;code>i&lt;/code> and &lt;code>j&lt;/code> such that :&lt;/p>
&lt;ul>
&lt;li>&lt;code>i != j&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= i, j &amp;lt; arr.length&lt;/code>&lt;/li>
&lt;li>&lt;code>arr[i] == 2 * arr[j]&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [10,2,5,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: N = 10 is the double of M = 5,that is, 10 = 2 * 5.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [7,1,14,11]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: N = 14 is the double of M = 7,that is, 14 = 2 * 7.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [3,1,7,11]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: In this case does not exist N and M, such that N = 2 * M.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>2 &amp;lt;= arr.length &amp;lt;= 500&lt;/code>&lt;/li>
&lt;li>&lt;code>-10^3 &amp;lt;= arr[i] &amp;lt;= 10^3&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一組整數陣列，檢查當中是否存在兩個數N, M使得N = 2 * M。&lt;br>
(留意不可使用重複的index)&lt;/p>
&lt;p>乍看之下有沒有覺得一陣熟悉？&lt;br>
沒錯，LeetCode最開始的第一題&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-1-400da76b51b4" target="_blank" rel="noopener"
>&lt;strong>0001.Two Sum&lt;/strong> &lt;/a>的套路，&lt;br>
跟這個非常的相似，只不過從兩數相加等於固定數，&lt;br>
變成一個是另一個的兩倍。另一方面，我們只要將存在與否輸出，&lt;br>
所以&lt;strong>不用記錄是什麼配對&lt;/strong> 。&lt;/p>
&lt;p>那麼，按照先前的做法，我們需要做的事情是：&lt;/p>
&lt;ol>
&lt;li>檢查&lt;strong>現在的值有沒有符合之前的配對&lt;/strong> ，若有，就直接回傳True即可。&lt;br>
 (先前使用HashMap/Dictionary，這次可以使用HashSet/Set)&lt;/li>
&lt;li>將&lt;strong>當前的值對應到的配對&lt;/strong> 擺進Set當中，&lt;br>
由於當前的值x對應到之後的y有可能是 x = 2 * y 或 y = 2 * x，&lt;br>
所以我們要一次將兩種可能都放進去。&lt;br>
這樣子整個Set的總大小會變成2N，但不會影響檢查速度。&lt;br>
(因為HashSet/Set同樣是使用hash function的機制)&lt;/li>
&lt;li>&lt;strong>全部檢查完，仍然沒有符合的狀況，則回傳False。&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，由於限制資料型態，&lt;br>
要留意處理除以2的部分，不能讓它自動做整數除法，&lt;br>
所以&lt;strong>先檢查能否被2整除，可以的狀況才將其加入Set中&lt;/strong> 。&lt;br>
(使用&lt;strong>HashSet&lt;/strong> ，檢查是否存在值使用&lt;strong>contains()&lt;/strong> ，&lt;strong>add()&lt;/strong> 來加入元素)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/5b1b9fe8c5063daa86b363ab7a1ed32c.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，由於/2直接會變成float，沒有特別被限制，&lt;br>
我們可以直接選擇加入而略過檢查的部分。&lt;br>
(反正小數點也不會被對到嘛XD)&lt;br>
(使用&lt;strong>set()&lt;/strong> 開一個Set，&lt;strong>in / not in&lt;/strong> 來檢查，並用&lt;strong>update&lt;/strong> 來加入多個元素)&lt;br>
(先處理存在或先處理不存在的狀況都可以，看自己的喜好)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1dd76266d42ee1fa49083750c5a97528.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，記得乘以2倍空間上是常數，不要講O(2N)歐XD)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 88 Hash Table (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-88-hash-table-8/</link><pubDate>Fri, 21 Feb 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-88-hash-table-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 88 Hash Table (8)" />&lt;p>&lt;strong>0575. Distribute Candies (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an integer array with ** even** length, where different numbers in this array represent different ** kinds** of candies. Each number means one candy of the corresponding kind. You need to distribute these candies ** equally** in number to brother and sister. Return the maximum number of ** kinds** of candies the sister could gain.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: candies = [1,1,2,2,3,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>There are three different kinds of candies (1, 2 and 3), and two candies for each kind.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Optimal distribution: The sister has candies [1,2,3] and the brother has candies [1,2,3], too.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The sister has three different kinds of candies.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: candies = [1,1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: For example, the sister has candies [2,3] and the brother has candies [1,1].
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The sister has two different kinds of candies, the brother has only one kind of candies.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>The length of the given array is in the range [2, 10,000], and will be even.&lt;/li>
&lt;li>The number in given array is in range [-100,000, 100,000].&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個偶數長度的整數陣列，當中不同的數字代表不同種類的糖果。&lt;br>
你要將糖果平分給一對兄妹(姐弟)，試算出當中姐姐/妹妹最多能拿到幾種不同種類的糖果。&lt;/p>
&lt;p>什麼？題目也偏女生嗎(大誤)&lt;/p>
&lt;p>題目內文基本上已經講得相當清楚了，&lt;br>
接下來問題就來到究竟我們要怎麼知道種類有多少種不同呢？&lt;br>
首先，如果每顆糖果都不同種類，女生最多能拿的也只有&lt;strong>一半&lt;/strong> ，&lt;br>
所以能拿到的種類上限會受限於&lt;strong>candies的總數除以2&lt;/strong> 。&lt;br>
這個是大前提，我們先將它放在一邊。&lt;/p>
&lt;p>那麼，如果&lt;strong>種類總數比candies總數的一半小&lt;/strong> 呢？&lt;br>
簡單的想法就是發糖果的時候，&lt;strong>每次遇到沒看過的種類，&lt;br>
就先記起來&lt;/strong>，藉此將整個種類數計數過一遍。&lt;br>
(或者你也可以想成&lt;strong>每次看到沒看過的種類&lt;/strong> 要優先給女生，&lt;br>
給到女生&lt;strong>拿滿&lt;/strong> 或&lt;strong>沒有新的種類&lt;/strong> 為止，兩個思考的模式和條件其實差不多。)&lt;/p>
&lt;p>要記錄某種糖果的出現數量，&lt;br>
自然會想到HashTable/HashSet/Dictionary這類的東西，&lt;br>
但由於題目有提到種類是從-100000~100000，&lt;br>
所以其實我們可以開出一個長度為200001的陣列/串列，&lt;br>
直接當成Hash Table來使用，只要位移個100000即可。&lt;br>
(陣列/串列要從0開始)&lt;/p>
&lt;p>因此，我們每次就可以從candies中依序取出一個數字，&lt;br>
將Hash Table內的對應位置進行遞增，再看看加完後是否剛好是1，&lt;br>
是1就代表這是新種類的糖果，所以要將種類的變數加1。&lt;/p>
&lt;p>最後再回頭比較種類的數量，跟糖果的總數的一半，&lt;br>
選擇較小的進行回傳即可。&lt;/p>
&lt;p>依此，寫成程式碼：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/de3b48a33603ea54a9137fcfb58e8768.js">&lt;/script>
&lt;p>Python的部分，我們也可以用set的方式取得不重複的種類，&lt;br>
再取其len()即可得到不重複的種類數量。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/264600a62b62ab38307a7df607d87be3.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，如果將空間固定成題目給定的限制的話，&lt;br>
會固定要開出一個200001的空間，這個可以再直接用說的。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 87 Bitwise Operation (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-87-bitwise-operation-6/</link><pubDate>Tue, 11 Feb 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-87-bitwise-operation-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 87 Bitwise Operation (6)" />&lt;p>&lt;strong>1342. Number of Steps to Reduce a Number to Zero (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a non-negative integer &lt;code>num&lt;/code>, return the number of steps to reduce it to zero. If the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: num = 14
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 1) 14 is even; divide by 2 and obtain 7.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 2) 7 is odd; subtract 1 and obtain 6.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 3) 6 is even; divide by 2 and obtain 3.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 4) 3 is odd; subtract 1 and obtain 2.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 5) 2 is even; divide by 2 and obtain 1.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 6) 1 is odd; subtract 1 and obtain 0.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: num = 8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 1) 8 is even; divide by 2 and obtain 4.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 2) 4 is even; divide by 2 and obtain 2.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 3) 2 is even; divide by 2 and obtain 1.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Step 4) 1 is odd; subtract 1 and obtain 0.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: num = 123
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 12
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>0 &amp;lt;= num &amp;lt;= 10^6&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個數字num，回傳其化簡至0所用的步驟數。&lt;br>
化簡的方法為：&lt;br>
若num此刻為偶數，將其除以2；若num此刻為奇數，將其減去1。&lt;/p>
&lt;p>這題如果按照題目的條件一步一步走的話，&lt;br>
以二進位制來看，&lt;br>
我們會發現當尾端的bit是1時，就必須&lt;strong>減去1並除以2&lt;/strong> ，&lt;br>
也就是向右位移一個bit(&lt;strong>這整件事情耗費了2步&lt;/strong> )；&lt;br>
若bit是0時，則只需要除以2即可。&lt;/p>
&lt;p>所以一個很簡單且直觀的寫法，就是利用迴圈，&lt;br>
當num還大於0時，檢查尾數的bit(可以用num &amp;amp; 1取得尾數是0或1)，&lt;br>
你可以用&lt;strong>三元運算子&lt;/strong> ，或者直接**(num &amp;amp; 1) + 1** 亦可，&lt;br>
請注意由於**&amp;amp;運算子的優先序較低** ，務必將num和1用括號包起來！&lt;br>
一路做到最後一個1，最後num等於0時就完成了。&lt;br>
(因為最後一個1不用再位移了，所以我們加總起來的步數最後要減去1)&lt;/p>
&lt;p>這裡提供另一個想法：&lt;br>
當我們沒有限制計算bitCount的函式及轉換二進位/字串時，&lt;br>
可以推想到：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>所有1都必須被消成0 (每個bit &amp;lsquo;1&amp;rsquo;會耗費1步)&lt;/strong>&lt;/li>
&lt;li>要除以幾次2，端看&lt;strong>最高位的1離個位數有多遠&lt;br>
(轉成二進位的總長減去1等於總共要除以2的次數)&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>所以我們得到： &lt;strong>答案 = num的bit ‘1’數量 + num的長度 - 1&lt;/strong>&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，我們可以利用bitCount和toBinaryString來達到要求。&lt;br>
(一步一步算的也有列出參考解，讀者可以自己試看看)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/ac7bed87672d4c13dc8df0fb361f460d.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，由於bin()轉二進位時，前面會多出**’0b’** ，&lt;br>
所以計算長度時會多出2，&lt;strong>後面的減1就會變成需要改成減3&lt;/strong> ，&lt;br>
請再留意。其他跟Java大同小異。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/2370b48ca224bdc83884be2e66e770f2.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(logN)/O(1)，但因為num最高就是10^6而已，如果你要宣稱num是constant，因此時間複雜度當成O(1)，個人覺得也是合理的。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;/strong>&lt;/p>
&lt;p>From &lt;a class="link" href="https://www.facebook.com/rollfatcat" target="_blank" rel="noopener"
>Cheng Rui Xie&lt;/a> :&lt;br>
位元運算有很多有趣的 function 可以呼叫：&lt;br>
回傳以二為底的次方項：&lt;strong>__lg(num)&lt;/strong>&lt;br>
回傳數字二進位後1的個數：&lt;strong>__builtin_popcount(num)&lt;/strong>&lt;br>
&lt;strong>只要取兩個的和即可且運算的時間＝O(1) &lt;br>
(這個想法的O(1)也是將num當限定大小看待。)&lt;/strong>&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 86 Hash Table (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-86-hash-table-7/</link><pubDate>Wed, 05 Feb 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-86-hash-table-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 86 Hash Table (7)" />&lt;p>&lt;strong>1331. Rank Transform of an Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of integers &lt;code>arr&lt;/code>, replace each element with its rank.&lt;/p>
&lt;p>The rank represents how large the element is. The rank has the following rules:&lt;/p>
&lt;ul>
&lt;li>Rank is an integer starting from 1.&lt;/li>
&lt;li>The larger the element, the larger the rank. If two elements are equal, their rank must be the same.&lt;/li>
&lt;li>Rank should be as small as possible.&lt;/li>
&lt;/ul>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [40,10,20,30]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [4,1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: 40 is the largest element. 10 is the smallest. 20 is the second smallest. 30 is the third smallest.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [100,100,100]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,1,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Same elements share the same rank.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: arr = [37,12,28,9,100,56,80,5,12]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [5,3,4,2,8,6,7,1,3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>0 &amp;lt;= arr.length &amp;lt;= 10^9&lt;/code>&lt;/li>
&lt;li>&lt;code>-10^9 &amp;lt;= arr[i] &amp;lt;= 10^9&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個陣列，將其依照大小順序排出rank。&lt;br>
(由1開始，大小相同則相同rank，數字越大，其rank則越大)&lt;/p>
&lt;p>由於我們需要按照大小相同來排定rank，所以顯然我們需要將其排序後，&lt;br>
才能知道誰應該在第幾個。對於這樣子的題目，&lt;br>
一般而言我們不需要自己實作排序的過程，除非面試官要求，&lt;br>
否則說明清楚你使用了排序即可；&lt;br>
不要忘記對於沒有特別安排的資料結構，&lt;br>
一般程式語言所使用的排序法基本上都是&lt;strong>O(N log N)&lt;/strong> 的時間複雜度，&lt;br>
所以最後在問複雜度時記得納入考量。&lt;/p>
&lt;p>既然我們需要取代原先的陣列，所以我們必須另外增加一組記憶體空間，&lt;br>
用來存放排序的狀態。存放好以後，應該要怎麼去記錄呢？&lt;br>
由於相同的數字要擁有相同的rank，對於存取和讀出擁有最快的複雜度的，&lt;br>
就是Hash Table了！我們可以先&lt;strong>檢查當下該數字是否已經放入對應&lt;/strong> ，&lt;br>
若還沒有放入對應，則需要寫入(number, rank)的對應。&lt;br>
這時候rank是多少呢？應該要將&lt;strong>已經置入的配對數量+1&lt;/strong> 來計算。&lt;br>
(因為代表現在已經給到多少數量的rank了)&lt;br>
都放完以後，再依序將陣列中的每個值作為key，&lt;br>
來從Hash Table得到其對應的rank(value)，再覆蓋掉即可。&lt;/p>
&lt;p>依此，寫成程式碼：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java在增加新的記憶體儲存一份陣列時，可以使用&lt;strong>Arrays.copyOf()&lt;/strong> 。&lt;br>
(後面加length可以指定複製的總長度)&lt;br>
使用HashMap來進行存放，並且用&lt;strong>putIfAbsent(key, value)&lt;/strong> ，&lt;br>
僅在&lt;strong>不存在對應時才進行寫入。&lt;br>
最後再利用HashMap.get()來一一取得對應rank並寫入。&lt;/strong>&lt;/p>
&lt;script src="https://gist.github.com/Desolve/c26de6387245a116951412cf2208820f.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，我們可以直接使用sorted(arr)取得一份新的串列。&lt;br>
也可以使用&lt;strong>list.copy()&lt;/strong> 或者&lt;strong>arr[:]&lt;/strong> 的方式來取得複製的串列。&lt;br>
&lt;strong>請注意 &amp;ldquo;sArr = arr&amp;rdquo; 和 &amp;ldquo;sArr = arr[:]&amp;ldquo;意義上是不同的，&lt;/strong>&lt;br>
&lt;strong>後者才是完整複製一份arr的串列&lt;/strong> ，前者是新增了一個變數名稱，&lt;br>
但其記憶體位址依舊是指向到arr的！(也就是後者並沒有進行複製)&lt;/p>
&lt;p>Java中使用HashMap，在Python中則用Dictionary達到，&lt;br>
而對應到putIfAbsent的函式則是&lt;strong>setdefault&lt;/strong> 。&lt;br>
(也可以用&lt;strong>if&lt;/strong> ** a not in rk: rk[a] = len(rk) + 1**)&lt;/p>
&lt;p>最後，&lt;strong>使用map函式來一一得到arr對應到rk.get的內容。&lt;/strong>&lt;br>
(即每次從arr依序取出元素再代入到rk.get內)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e63f544f4b1d7d58cdfcbc7c6fc96b14.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(NlogN)/O(N))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 85 String (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-85-string-3/</link><pubDate>Thu, 30 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-85-string-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 85 String (3)" />&lt;p>&lt;strong>1332. Remove Palindromic Subsequences (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string &lt;code>s&lt;/code> consisting only of letters &lt;code>'a'&lt;/code> and &lt;code>'b'&lt;/code>. In a single step you can remove one palindromic &lt;strong>subsequence&lt;/strong> from &lt;code>s&lt;/code>.&lt;/p>
&lt;p>Return the minimum number of steps to make the given string empty.&lt;/p>
&lt;p>A string is a subsequence of a given string, if it is generated by deleting some characters of a given string without changing its order.&lt;/p>
&lt;p>A string is called palindrome if is one that reads the same backward as well as forward.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;ababa&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: String is already palindrome
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;abb&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: &amp;#34;abb&amp;#34; -&amp;gt; &amp;#34;bb&amp;#34; -&amp;gt; &amp;#34;&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Remove palindromic subsequence &amp;#34;a&amp;#34; then &amp;#34;bb&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;baabb&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: &amp;#34;baabb&amp;#34; -&amp;gt; &amp;#34;b&amp;#34; -&amp;gt; &amp;#34;&amp;#34;.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Remove palindromic subsequence &amp;#34;baab&amp;#34; then &amp;#34;b&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>0 &amp;lt;= s.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>s&lt;/code> only consists of letters &amp;lsquo;a&amp;rsquo; and &amp;lsquo;b&amp;rsquo;&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串，當中僅由&amp;rsquo;a&amp;rsquo;或&amp;rsquo;b&amp;rsquo;的字母所構成，每次你可以從中移除一個palindrome subsequence. 試回傳將該字串刪成空字串所需的最小步數。&lt;/p>
&lt;p>我們先前有講過subsequence的定義，可以參照之前的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-78-two-pointer-4-binary-search-5-49e21e35d2a5" target="_blank" rel="noopener"
>&lt;strong>題目&lt;/strong> &lt;/a>。&lt;br>
所以每次要移除掉一個subsequence且必須符合palindrome的條件，&lt;br>
乍看之下似乎不容易。&lt;br>
但選這題的目的就是要告訴大家，有時候事情並沒有想像中那麼複雜，&lt;br>
靜下心來好好推敲，可能可以找到適合的規律，&lt;br>
不要急著找通解，先試著去&lt;strong>用上所有已知的條件&lt;/strong> 看看才對！&lt;/p>
&lt;p>我們知道subsequence就是按照排列的先後順序取就可以了，&lt;br>
但&lt;strong>palindrome(回文)&lt;/strong> 則必須取出來從頭到尾和從尾到頭一致才行。&lt;/p>
&lt;p>我們先考慮最簡單的部分，再慢慢往下推。&lt;br>
&lt;strong>1. 當字串是空白的時候：&lt;/strong>&lt;br>
&lt;strong>不需操作&lt;/strong> 即可達到條件，&lt;strong>所以總step為0。&lt;br>
2. 當字串本身就是palindrome：&lt;br>
把整個字串做為subsequence移除，所以總step為1。&lt;/strong>&lt;/p>
&lt;p>接下來是最重要的部分，&lt;br>
如果字串本身不是palindrome的話，&lt;br>
要怎麼樣才會移除一個palindrome sequence後，&lt;br>
可以用最小步數化簡呢？&lt;br>
&lt;strong>由於s僅僅由’a’和’b’所組成&lt;/strong> ，&lt;br>
所以我們可以考慮&lt;strong>直接移去全部的&amp;rsquo;a&amp;rsquo;或全部的&amp;rsquo;b&amp;rsquo;，&lt;br>
由於全部都是&amp;rsquo;a&amp;rsquo;或全部都是&amp;rsquo;b&amp;rsquo;也是一種palindrome，&lt;br>
所以符合前面移除的規則；&lt;br>
而剩下來的就全部都是另外一種字元，&lt;br>
同樣也構成palindrome。&lt;br>
因此，最多只要2個step，就能全數移完。&lt;/strong>&lt;/p>
&lt;p>(想一下，如果今天是有N種不同的字元構成s，&lt;br>
最多就會需要N個step，但這只是上限而已，而不是minimum steps。)&lt;/p>
&lt;p>有興趣寫更細的話，可以用two pointer來寫這題的檢查palindrome的部分，&lt;br>
這裡就直接用簡單的操作處理。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，操作&lt;strong>reverse&lt;/strong> 要使用&lt;strong>StringBuilder&lt;/strong> 來處理，&lt;br>
處理完以後，再轉回String。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/05c2e5731e195ddd44754fd326e3e8cc.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分更精簡，使用**[::-1]** 即可表達&lt;strong>從尾到頭&lt;/strong> 的部分。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1739bde8255945c392e5c87dec946573.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，若願意一個一個字元比較的話，&lt;br>
空間複雜度也可以降到O(1)，也就是用簡單的two pointer處理即可)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 84 Tree (11) / DFS (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/</link><pubDate>Fri, 24 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 84 Tree (11) / DFS (8)" />&lt;p>&lt;strong>0116. Populating Next Right Pointers in Each Node (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are given a &lt;strong>perfect binary tree&lt;/strong> where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>struct Node {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> int val;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Node *left;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Node *right;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Node *next;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>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>NULL&lt;/code>.&lt;/p>
&lt;p>Initially, all next pointers are set to &lt;code>NULL&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>You may only use constant extra space.&lt;/li>
&lt;li>Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.&lt;/li>
&lt;/ul>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001.png"
width="800"
height="273"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001_hu87da30d3ed309667da43321bfdaf6c7c_59970_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-84-tree-11-dfs-8/image-001_hu87da30d3ed309667da43321bfdaf6c7c_59970_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="293"
data-flex-basis="703px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [1,2,3,4,5,6,7]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,#,2,3,#,4,5,6,7,#]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>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>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個完美二元樹(perfect binary tree)，&lt;br>
也就是所有葉子都在相同level且所有父節點均有兩個子節點。&lt;br>
在Node的定義中增加一個next的定義，&lt;br>
如圖所示，每個節點的next為其右邊的節點，&lt;br>
如右邊已無節點，則為NULL。&lt;br>
(最開始的時候預設所有節點的next均為NULL)&lt;br>
請把整個next的定義完成。&lt;/p>
&lt;p>由於這個題目已經有提到說只能用常數的額外記憶體空間了，&lt;br>
但同時將遞迴導致的stack(也就是call stack)當作不算，&lt;br>
所以使用簡單的遞迴可以簡單達到目的。&lt;/p>
&lt;p>最直觀的方式，就是先檢查root是否是null，&lt;br>
接下來呼叫一個helper function，代入左節點和右節點來處理，&lt;br>
只要左節點不是NULL，則將左節點的next設為右節點；&lt;br>
接下來則要分別處理這三個連接：&lt;br>
&lt;strong>1. 左節點的left -&amp;gt; 左節點的right&lt;br>
2. 左節點的right -&amp;gt; 右節點的left&lt;br>
3. 右節點的left -&amp;gt; 右節點的right&lt;/strong>&lt;/p>
&lt;p>當然，也可以從root為中心出發，&lt;br>
這時候每次要關注的應該是root.left -&amp;gt; root.right，&lt;br>
及root.right -&amp;gt; root.next.left。&lt;/p>
&lt;p>如果想要用迭代的方式呢？&lt;br>
我們留意到每次開始進行連接的都是當個階層的最左邊的節點，&lt;br>
從&lt;strong>Figure B&lt;/strong> 上來看的話，即為1, 2, 4…等節點。&lt;br>
所以我們最開始應該要從一個階層的最左邊的節點&lt;br>
(這邊叫做level_first)開始進行迭代，將當前的節點稱為curr&lt;br>
分別將&lt;strong>curr.left -&amp;gt; curr.right&lt;/strong> 及&lt;strong>curr.right -&amp;gt; curr.next.left。&lt;br>
接著讓curr遞移到curr.next。&lt;br>
所以每次連接兩組next的關係，直到curr走到NULL為止。&lt;br>
這時候這層走完以後，進行到下一層，&lt;br>
level_first應該遞移到level_first.left。&lt;/strong>&lt;/p>
&lt;p>依此，寫成如下的程式碼。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>在Java中，上述三種方法均有列出，&lt;br>
順序剛好跟上面提到的相反，&lt;br>
請務必留意在接續前必須要留意要確定節點是否為null的狀況。&lt;br>
如果計入call stack的話，只有迭代的方式是O(1)才對。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/889bec573f69f5640c33455484b98209.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分大同小異，不要忘記使用self來呼叫，&lt;br>
這邊僅列出第二種和第三種。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/58b0d724cf6dc9a63281d6eb428989b2.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，如果不考慮Call Stack的話。&lt;br>
如果考慮的話上面只有直接使用迴圈迭代的是O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 83 Dynamic Programming (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-83-dynamic-programming-10/</link><pubDate>Wed, 15 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-83-dynamic-programming-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 83 Dynamic Programming (10)" />&lt;p>&lt;strong>0091. Decode Ways (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>A message containing letters from &lt;code>A-Z&lt;/code> is being encoded to numbers using the following mapping:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>&amp;#39;A&amp;#39; -&amp;gt; 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#39;B&amp;#39; -&amp;gt; 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#39;Z&amp;#39; -&amp;gt; 26
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Given a &lt;strong>non-empty&lt;/strong> string containing only digits, determine the total number of ways to decode it.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;12&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: It could be decoded as &amp;#34;AB&amp;#34; (1 2) or &amp;#34;L&amp;#34; (12).
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;226&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: It could be decoded as &amp;#34;BZ&amp;#34; (2 26), &amp;#34;VF&amp;#34; (22 6), or &amp;#34;BBF&amp;#34; (2 2 6).
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個訊息，當中A到Z以1至26的方式依序對應，&lt;br>
用數字的編碼方式寫成一個字串。&lt;br>
給定這樣子一個僅含數字1~9組成的字串，&lt;br>
試決定所有可以解碼的方法數。&lt;/p>
&lt;p>這題在LeetCode上面比較有問題的點在於，&lt;br>
沒有硬性規定&lt;strong>開頭或結尾多出來的0&lt;/strong> 的部分。&lt;br>
所以這邊我們會再加上一個條件，&lt;br>
&lt;strong>一旦開頭有0或中間有碰到多餘的0&lt;/strong> 的部分，&lt;br>
就當作可以接續下去(不當作錯誤)，&lt;br>
這樣看起來會比較符合測資測出來的結果。&lt;/p>
&lt;p>首先會考慮到就當下而言，如果是空字串的話，&lt;br>
應該要直接先回傳0**(雖然沒有字串嚴格來說也是1種方法，&lt;br>
但給題目來說就要代表沒有辦法解碼)&lt;strong>。&lt;br>
如果是考慮每個字串起始檢查的狀況，&lt;br>
則應該會將起始條件設定為&lt;/strong>1種可能。**&lt;/p>
&lt;p>接下來我們考慮往下走的時候，怎麼樣可以構成可能的字組呢？&lt;br>
我們假定從index 0開始的各種子字串，&lt;br>
均已知有幾種方法了，那麼，當我們在index i的位置時，&lt;br>
要如何決定到這邊的方法數呢？其實不難思考。&lt;/p>
&lt;p>由於我們的英文字母可能性是從1&lt;del>26，&lt;br>
所以如果**index i對應的值是1&lt;/del>9之間** 的話，&lt;br>
代表它獨立可以成為一種可能性，&lt;br>
也就是&lt;strong>走到前面i-1的狀況，再加上i這邊單獨代表的字母&lt;/strong> 。&lt;br>
這麼考慮的話&lt;strong>走到i的組合數就和走到i-1的組合數是相同的&lt;/strong> 。&lt;br>
(以index i位置的值單獨成立的狀況來說)&lt;/p>
&lt;p>那麼還有另一種可能，&lt;br>
就是index i-1和index i所組成的二位數也能代表字母，&lt;br>
這個數字應該是&lt;strong>10~26&lt;/strong> 之間，所以這種狀況成立的條件下，&lt;br>
&lt;strong>走到i的組合數和走到i-2的組合數相同&lt;/strong> 。&lt;/p>
&lt;p>所以歸納上述兩點，我們必須要分別檢查，&lt;br>
然後決定是否要將i-1的方法數及i-2的方法數加進來。&lt;/p>
&lt;p>感覺是不是有點像之前的House Robber?&lt;br>
所以這也是一個典型的Dynamic Programming題目。&lt;br>
依此，我們可以定一個array或list，取名叫&lt;strong>dp&lt;/strong> ，&lt;br>
&lt;strong>長度為s的長度加1。&lt;/strong>&lt;/p>
&lt;p>我們將可能的兩位數分別叫做prev跟curr，&lt;br>
那麼每次要作的事情，就如同上面所述一樣：&lt;/p>
&lt;ol>
&lt;li>初始化&lt;strong>dp[0] = 1&lt;/strong> , &lt;br>
&lt;strong>dp[1] = 1 (如果第一個字不是'0&amp;rsquo;) or 0 (如果第一個字是'0&amp;rsquo;)&lt;/strong>&lt;/li>
&lt;li>迴圈讓i從2&lt;del>l，&lt;br>
每次將&lt;strong>curr的值遞移到prev，prev則取得s[i-1]&lt;/strong> 的值。&lt;br>
當&lt;strong>curr非0&lt;/strong> 的時候(即1&lt;/del>9)，我們可以將&lt;strong>dp[i-1]加到dp[i]&lt;/strong> 中；&lt;br>
當&lt;strong>prev和curr&lt;/strong> 可以組成&lt;strong>10~26之間&lt;/strong> 的值時，可以將&lt;strong>dp[i-2]加到dp[i]&lt;/strong> 中。&lt;/li>
&lt;li>迴圈結束後，回傳&lt;strong>dp[l]&lt;/strong> 即可。&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼如下。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，也可以順便檢查s是否為null，&lt;br>
但本題的測資似乎也沒有刁難這個部分(題目有說均為數字)。&lt;br>
檢查&lt;strong>10~26&lt;/strong> 的部分，&lt;br>
可以拆成(&lt;strong>prev==’1’)&lt;/strong> 或(&lt;strong>prev == ‘2’且curr ≤ ’6’)&lt;/strong> 檢驗。 &lt;strong>對Java而言，&lt;br>
char可以直接用數字的方式(ASCII Code)的狀態來比大小，&lt;br>
所以我們不用再轉成Integer來浪費時間XD&lt;/strong>&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e75f8c280ddae8ee783551388dd09009.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，也可以&lt;strong>直接比大小&lt;/strong> ，其實作是呼叫ord()函數，&lt;br>
來取得比大小所需的ASCII Code數字，&lt;br>
但就沒辦法像Java的char那樣很多花樣了。&lt;/p>
&lt;p>提醒大家，在寫的時候請務必留意範圍，&lt;br>
以本題為例，由於&lt;strong>dp[0]&lt;/strong> 是被佔用做為初始值的，&lt;br>
所以我們在寫的時候&lt;strong>i是對應由1為準起算的。&lt;/strong>&lt;/p>
&lt;script src="https://gist.github.com/Desolve/51589115429e6a36335017a990c03510.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，N為字串長度)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9Q5VE" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VE9Q5VE**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 82 Linked List (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-82-linked-list-10/</link><pubDate>Thu, 09 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-82-linked-list-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 82 Linked List (10)" />&lt;p>&lt;strong>0086. Partition List (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>再過兩天就是投票日了，懇請各位讀者們，&lt;br>
不論支持誰，都要好好地去了解候選人們及政黨的政見，&lt;br>
在1/11投下您寶貴的一票。**&lt;/p>
&lt;p>&lt;strong>筆者在這裡提醒大家去思考一下：&lt;br>
程式的世界很單純，很多東西不是True就是False，&lt;br>
而一個按照正常邏輯運行的程式，最終該呈現怎樣的結果，&lt;br>
大抵都是可以預期的。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>想像一下，如果一個同事常常遲到早退，罔顧專案進度，&lt;br>
讓大家必須要幫忙收拾爛攤子；&lt;br>
話說的很滿，遇到事情卻推拖閃躲，&lt;br>
顧左右而言他的話，相信這樣的人，&lt;br>
我們不會希望其成為自己的頂頭上司。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>既然如此，我們會希望這種人成為自己的大老闆嗎？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>運用簡單的邏輯思考，相信聰明的各位都能得到正確答案。&lt;br>
儘管這種人的餅畫得再大再漂亮，我們知道，&lt;br>
那都不是真的，因為我們難以相信一個沒有誠信的人能夠說到做到。&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a linked list and a value &lt;em>x&lt;/em>, partition it such that all nodes less than &lt;em>x&lt;/em> come before nodes greater than or equal to &lt;em>x&lt;/em>.&lt;/p>
&lt;p>You should preserve the original relative order of the nodes in each of the two partitions.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: head = 1-&amp;gt;4-&amp;gt;3-&amp;gt;2-&amp;gt;5-&amp;gt;2, x = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2-&amp;gt;2-&amp;gt;4-&amp;gt;3-&amp;gt;5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個Linked List和一個值x，使用x來將所有節點進行分段，&lt;br>
令較x小的節點排在≥x的分段位置的前面。&lt;br>
注意在分段時，同時也要保有原先兩段的節點順序。&lt;/p>
&lt;p>這題其實有點像是之前我們在講&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-4-6a631eb50da3" target="_blank" rel="noopener"
>Merge Two Sorted Lists&lt;/a>的感覺，&lt;br>
為了要能夠讓兩個段落分開且照順序，&lt;br>
我們應該要有兩個做為頭的&lt;strong>dummy節點&lt;/strong> ，稱為d1/d2。&lt;br>
所有小於x的部分都接到d1，反之則接到d2。&lt;br>
那麼實際上來說，我們只要將整個List遍歷過一遍，&lt;br>
就可以依照&lt;strong>實際和x之間的比較，來決定要將這次看到的節點&lt;/strong> ，&lt;br>
必須要接到d1還是d2上面。&lt;/p>
&lt;p>由於最後我們需要將兩段接起來，&lt;br>
所以d1/d2保持不動的狀況下，&lt;br>
我們需要另一個變數來&lt;strong>儲存現在遍歷的部份走到的節點，&lt;br>
先稱其為ite1/ite2，所以ite1/ite2起始分別是d1/d2。&lt;/strong>&lt;/p>
&lt;p>那麼，按照邏輯來說，我們可以能會想到下面的寫法：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>if (head.val &amp;lt; x) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 　ite1.next = head;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 　ite1 = ite1.next;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>但這麼考慮欠缺了一個條件：&lt;br>
&lt;strong>當我們選定ite1.next = head時，head裡面還藏有它的next的資訊&lt;/strong> ，&lt;br>
造成你以為是只有納入head，&lt;strong>殊不知head.next也被隱含進去了&lt;/strong> ！&lt;br>
要解決這個問題，我們可以&lt;strong>將ite1.next重新設為null&lt;/strong> 。&lt;br>
問題來了，這一設為null，反而變成&lt;strong>head的資訊就消失了&lt;/strong> ，&lt;br>
&lt;strong>同時head.next的資訊也消失了&lt;/strong> 。&lt;/p>
&lt;p>所以，我們要一開始用一個nxt的ListNode來記錄head.next，&lt;br>
接下來兩種狀況下的next相關操作做完以後，&lt;br>
&lt;strong>最後再讓head接上先前儲存的nxt。&lt;/strong>&lt;/p>
&lt;p>依此，寫成程式碼。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，我們先用直觀的方式來處理，&lt;br>
所以包含前面的處理都完整的話，&lt;br>
我們應該能得到&lt;strong>d1及其後面的一組(直到ite1)、&lt;br>
d2及其後面的另一組(直到ite2)&lt;/strong>，&lt;br>
若其中一個沒有接上任何節點的話，&lt;br>
可以&lt;strong>直接吐出d1.next/d2.next&lt;/strong> 的狀況。&lt;br>
若兩者皆有，則&lt;strong>先將第一排的結尾接給第二排的開頭&lt;/strong> ，&lt;br>
最後回傳d1.next即可。&lt;/p>
&lt;p>同時，運用陣列可以更輕鬆地化簡邏輯，&lt;br>
這裡將改善過後的版本放在註解欄中。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/a4bf11639b8cd187f52e0d455277fe02.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>就Python的部分而言，只要使用跟前述相近的處理方式，&lt;br>
&lt;strong>最後再回傳d1.next&lt;/strong> 即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/ba6d096a47b698a49714560a9c591f88.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VEQZV7E**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 81 Backtracking (5) / DFS (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-81-backtracking-5-dfs-7/</link><pubDate>Tue, 07 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-81-backtracking-5-dfs-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 81 Backtracking (5) / DFS (7)" />&lt;p>&lt;strong>0093. Restore IP Addresses (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string containing only digits, restore it by returning all possible valid IP address combinations.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;25525511135&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;255.255.11.135&amp;#34;, &amp;#34;255.255.111.35&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個僅含數字0~9的字串，將其還原成所有合法的IP位址的可能組合。&lt;/p>
&lt;p>對於IP而言，我們所需考慮的有以下幾個條件：&lt;br>
&lt;strong>1. 共分4段(且必須恰好是4段)&lt;/strong>&lt;br>
&lt;strong>2. 中間以小數點連接，每組的數字在0~255之間&lt;/strong>&lt;/p>
&lt;p>如果定義再清楚一點的話，&lt;br>
可以補上前面寫0的部分除了0以外不能納入，會更好一點。&lt;br>
(比如113.002.22.3不會是合法的IP，但一個IP可以是0.0.0.0)&lt;/p>
&lt;p>所以這題也是很典型的&lt;strong>Backtracking+DFS&lt;/strong> 的題目：&lt;br>
&lt;strong>每次從s上面按順序取一段長度，檢查它是否合法，&lt;br>
再遞迴取下一段。&lt;/strong>&lt;/p>
&lt;p>那麼，我們需要考慮一些邊界的條件，&lt;br>
以便於我們考慮什麼時候該「回頭」：&lt;br>
最基本的條件，就是&lt;strong>已經分到第4段&lt;/strong> 了，&lt;br>
我們應該要考慮這段剩下的部分是否合法。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>當剩下的長度&amp;gt;3&lt;/strong> =&amp;gt; 根本就超過了，完全不用考慮XD&lt;/li>
&lt;li>&lt;strong>剩下的長度≤3且轉成數字≤255&lt;/strong> ，即可將該段補齊並加到結果。&lt;br>
例外：連續的0會有問題，所以要優先檢查是否&lt;strong>剛好為'0&amp;rsquo;&lt;/strong> 的狀況，&lt;br>
&lt;strong>除了剛好為&amp;quot;0&amp;quot;的狀況外，首字元為'0&amp;rsquo;就必須被排除掉&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>邊界條件考慮完後，我們來考慮一般的分段法。&lt;/p>
&lt;p>在開始之前，可以&lt;strong>先排除掉剩下的長度小於所需的分段數&lt;/strong> 的狀況，&lt;br>
用以避免取分段時超出邊界。&lt;br>
(例如剩下長度為2，但還需要取3段，那麼顯然不夠用)&lt;/p>
&lt;p>假設現在我們接下來要取的位置在 &lt;strong>i&lt;/strong> ，要取 &lt;strong>j&lt;/strong> 個字元：&lt;br>
那麼 &lt;strong>j可以是1~3，但 i+j 不能超過s的長度&lt;/strong> 。&lt;br>
我們會發現&lt;strong>額外要考慮的就是上面的2的部分&lt;/strong> ，&lt;br>
取完一段以後，呼叫相同的函式進行遞迴，&lt;br>
不要忘記除了上一次傳進來的&lt;strong>前導字串cur&lt;/strong> 外，&lt;br>
要加上的是&lt;strong>這次取的分段&lt;/strong> ，以及&lt;strong>分隔用的小數點&amp;quot;.&amp;quot;&lt;/strong> 。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，我們使用LinkedList來記錄結果res，&lt;br>
傳入的參數有該字串s，res，當前要取的索引值i，&lt;br>
當前的分段cnt(從0起算)，以及到目前為止的IP的字串cur。&lt;br>
由於每次呼叫checkIP時帶進去的字串都是&lt;strong>新生成&lt;/strong> 的，&lt;br>
所以回到上一層時就自然還原了cur的狀態，&lt;br>
不用像之前的棋盤搜尋字串問題中需要額外考慮要還原的問題。&lt;br>
&lt;strong>每次開始前不要忘記檢查s.length()-i &amp;lt; 4 - cnt的邊界&lt;/strong> ，&lt;br>
若已經不符則可直接return。&lt;br>
&lt;strong>(註：理論上也可以額外檢查s.length()-i &amp;gt; (4-cnt)*4的邊界，&lt;br>
但實測上並不會因此變快，推估可能理由和檢查255的問題一樣)&lt;/strong>&lt;/p>
&lt;p>另外請務必留意在比較字串是否相等時&lt;strong>請使用equals()的函式&lt;/strong> ，&lt;br>
&lt;strong>不要使用&amp;quot;==&amp;quot;(會出錯)&lt;/strong> 。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1ae57afd061a562a0eab62b379fed9b4.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分也是一樣的概念，&lt;br>
只是substring的操作可以簡單用&lt;strong>s[i:j]&lt;/strong> 的形式來處理，&lt;br>
且比較相等可以直接使用&amp;quot;==&amp;quot;。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/8c7e831c5468b6b48e5334890e3613fb.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(len(s)) / O(len(s))，更廣義來說，其實&lt;strong>長度必須在12&lt;/strong> 以內，&lt;br>
所以&lt;strong>最大的佔用空間和時間是可以固定的&lt;/strong> ，&lt;br>
要說O(1)也不太算有錯就是了。)&lt;/p>
&lt;p>「為什麼不是當3位數才檢查小於等於255？」&lt;br>
(這樣必須要先分開3位數及其他，變成要先經過另一組判斷式，&lt;br>
整體而言不會比較節省時間。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VEQZV7E**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 80 Linked List (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-80-linked-list-9/</link><pubDate>Sat, 04 Jan 2020 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-80-linked-list-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 80 Linked List (9)" />&lt;p>&lt;strong>0082. Remove Duplicates from Sorted List II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only &lt;em>distinct&lt;/em> numbers from the original list.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;3-&amp;gt;3-&amp;gt;4-&amp;gt;4-&amp;gt;5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2-&amp;gt;5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;1-&amp;gt;1-&amp;gt;2-&amp;gt;3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2-&amp;gt;3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個排序好的鏈結串列，將擁有重複的數字的節點全數刪去，&lt;br>
只保留原先在串列上相異的數字。&lt;/p>
&lt;p>我們之前就嘗試過&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-10-linked-list-2-8384845e8ad6" target="_blank" rel="noopener"
>&lt;strong>從鏈結串列刪去節點&lt;/strong> &lt;/a>的題目了，&lt;br>
只是今天這組更激進一點XD&lt;br>
原本是刪到剩一個即可，現在變成要將重複的全都刪掉，&lt;br>
那麼，該怎麼辦呢？&lt;/p>
&lt;p>由於有可能刪到第一個，一般來說這種狀況，&lt;br>
習慣上會開出一個dummy node做為不會變動的節點參照，&lt;br>
我們先將其叫做dum，簡單將dum的next連接至head即可。&lt;/p>
&lt;p>接下來要處理的是：我們要記得&lt;strong>數值一致的節點群前面的那一個節點&lt;/strong> ，&lt;br>
這樣刪去的時候才能將前後重新連接上。&lt;br>
因此，我們需要一個節點記錄，這裡將它叫做&lt;strong>pre&lt;/strong> ；&lt;br>
另一個節點則做為迭代用，記錄現在所在的位置，將其稱做&lt;strong>cur&lt;/strong> ，且就位置關係來說，&lt;strong>pre的next應該會是cur&lt;/strong> 。&lt;br>
開始時&lt;strong>pre的起始點&lt;/strong> 應該是&lt;strong>dum&lt;/strong> ，這樣&lt;strong>cur&lt;/strong> 會從&lt;strong>head&lt;/strong> 開始，&lt;br>
&lt;strong>當cur還沒走到底的時候要進行迴圈遍歷&lt;/strong> 。&lt;br>
另外在內部&lt;strong>每次要迴圈檢查&lt;/strong> ：&lt;br>
&lt;strong>1. cur是否有下一個節點&lt;/strong>&lt;br>
&lt;strong>且&lt;/strong>&lt;br>
&lt;strong>2. cur的下一個節點和自己的值是否相等&lt;/strong>&lt;br>
(和先前一樣，這個迴圈用來&lt;strong>略過所有重複值的節點&lt;/strong> )&lt;/p>
&lt;p>當走完以後有可能是&lt;/p>
&lt;ol>
&lt;li>&lt;strong>cur還沒到底(有值)&lt;/strong> =&amp;gt; &lt;br>
&lt;strong>pre的next就是cur&lt;/strong> ，所以再往下找的話要將&lt;strong>pre設為pre.next&lt;/strong>&lt;/li>
&lt;li>&lt;strong>cur已經碰到底了&lt;/strong> (cur.next == null) =&amp;gt;&lt;br>
將&lt;strong>pre.next指向null&lt;/strong> (pre.next = cur.next)&lt;/li>
&lt;/ol>
&lt;p>最後，別忘了&lt;strong>將cur往下走(cur = cur.next)&lt;/strong> 。&lt;br>
最終做完的時候，由於先前我們&lt;strong>將dum.next設定成head&lt;/strong> ，&lt;br>
中間連接有變動的話，會被pre的操作給連接過去，&lt;br>
&lt;strong>所以新的head的位置不管有無更動，&lt;br>
應該還是位於dum.next上。&lt;/strong>&lt;br>
(&lt;strong>因為pre一開始等於dum，pre.next一開始會連動到dum.next&lt;/strong> )&lt;/p>
&lt;p>依此，寫成程式碼。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分不要忘記該new的dum，&lt;br>
剩下就只有判斷null的時候不像Python可以直接用if not，&lt;br>
其他大多大同小異；Python的邏輯是一致的，就不再贅述說明了。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/6e999e9f0ca340173be77592141b0a94.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0f125ecd017b73b7ac5501941b00976e.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>這題理論上也可以用遞迴的方法解，有興趣的讀者可以嘗試看看。&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(最後一波早鳥優惠了，不確定調回原價是什麼時候)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VEQZV7E**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 79 Hash Table (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-79-hash-table-6/</link><pubDate>Tue, 31 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-79-hash-table-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 79 Hash Table (6)" />&lt;p>&lt;strong>0383. Ransom Note (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines; otherwise, it will return false.&lt;/p>
&lt;p>Each letter in the magazine string can only be used once in your ransom note.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;br>
You may assume that both strings contain only lowercase letters.&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>canConstruct(&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;) -&amp;gt; false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>canConstruct(&amp;#34;aa&amp;#34;, &amp;#34;ab&amp;#34;) -&amp;gt; false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>canConstruct(&amp;#34;aa&amp;#34;, &amp;#34;aab&amp;#34;) -&amp;gt; true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>繼&lt;strong>時空旅人買賣股票(&lt;/strong> &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-37-dynamic-programming-8-f60ad427d76d" target="_blank" rel="noopener"
>&lt;strong>0121&lt;/strong> &lt;/a>&lt;strong>)&lt;/strong> 及&lt;strong>闖空門教學(&lt;/strong> &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-28-dynamic-programming-6-8e5a81a8437d" target="_blank" rel="noopener"
>&lt;strong>0198&lt;/strong> &lt;/a>&lt;strong>,&lt;/strong> &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-29-dynamic-programming-7-8e3aedb07ca3" target="_blank" rel="noopener"
>** 0213**&lt;/a>** )&lt;strong>後，&lt;br>
我們這次要來寫&lt;/strong>勒索信** 啦！&lt;br>
有沒有覺得這一系列很實用？(大誤)&lt;/p>
&lt;p>勒索信的構成很簡單，就是每個從雜誌上的字，&lt;br>
剪下來以後&lt;strong>只能用一次&lt;/strong> ，要用這些字去組出勒索信的內容。&lt;/p>
&lt;p>所以這個就很簡單就可以處理啦！&lt;br>
我們可以先將所有雜誌上的字分門別類，&lt;br>
這邊還很貼心告訴我們&lt;strong>全部只有小寫字母&lt;/strong> ，&lt;br>
所以分成a-z即可，計算總共有的素材數量。&lt;/p>
&lt;p>接下來用勒索信上的每個字來去檢驗，&lt;br>
每次都扣除掉對應的字母的計數，中間一旦有素材不夠，&lt;br>
表示已經沒辦法完成信件，即可回傳false，&lt;br>
否則整個迴圈完成的話表示可構成勒索信，則回傳true。&lt;/p>
&lt;p>依此可以寫成程式碼。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，其實如要扣掉一些條件，&lt;br>
可以先檢查兩者的長度，magazine長度比較小時肯定無法完成勒索信。&lt;br>
由於題目的給定，我們可以不用HashMap，&lt;br>
僅用一個長度26的陣列來處理，index則用&lt;strong>c - ‘a’&lt;/strong> 來計算，&lt;br>
留意使用&amp;ndash;table[c-&amp;lsquo;a&amp;rsquo;]時由於&lt;strong>先進行遞減&lt;/strong> ，所以檢查條件是小於0。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/8e24d2e832ae7d1379d1d485375f890a.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，可以用dictionary作到類似的事情。&lt;br>
(list也可以，不過要自行用ord來轉換，和Java不同)&lt;br>
當然，我們也可以使用Counter或count來做更迅速的計算。&lt;br>
(註解提供了另外兩種leetcode上別人的解法)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/d8fbf7b9d72a6292d129de62f4ac5add.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(len(ransomNote) + len(magazine))/O(1))&lt;br>
(空間複雜度因為依題目提示，key值固定最多26，&lt;br>
所以不因字串長而改變。)&lt;/p>
&lt;p>「如果要求含大小寫/大小寫可混用/含標點符號等狀況呢？」&lt;br>
(依照所需使用HashMap或Dictionary，&lt;br>
並將共用的部分利用他們相減的距離歸到同類)&lt;br>
(在ASCII Code上，&lt;strong>‘a’-’A’ == 32&lt;/strong> )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(接下來快要漲成下個價格啦XD)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VEQZV7E**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 78 Two Pointer (4) / Binary Search (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-78-two-pointer-4-binary-search-5/</link><pubDate>Sat, 28 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-78-two-pointer-4-binary-search-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 78 Two Pointer (4) / Binary Search (5)" />&lt;p>&lt;strong>0392. Is Subsequence (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a string &lt;strong>s&lt;/strong> and a string ** t**, check if ** s** is a subsequence of ** t**.&lt;/p>
&lt;p>You may assume that there are only lower case English letters in both &lt;strong>s&lt;/strong> and ** t**. ** t** is potentially a very long (length ~= 500,000) string, and ** s** is a short string (&amp;lt;=100).&lt;/p>
&lt;p>A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, &lt;code>&amp;quot;ace&amp;quot;&lt;/code> is a subsequence of &lt;code>&amp;quot;abcde&amp;quot;&lt;/code> while &lt;code>&amp;quot;aec&amp;quot;&lt;/code> is not).&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;strong>s&lt;/strong> = &lt;code>&amp;quot;abc&amp;quot;&lt;/code>, ** t** = &lt;code>&amp;quot;ahbgdc&amp;quot;&lt;/code>&lt;/p>
&lt;p>Return &lt;code>true&lt;/code>.&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;strong>s&lt;/strong> = &lt;code>&amp;quot;axc&amp;quot;&lt;/code>, ** t** = &lt;code>&amp;quot;ahbgdc&amp;quot;&lt;/code>&lt;/p>
&lt;p>Return &lt;code>false&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;br>
If there are lots of incoming S, say S1, S2, … , Sk where k &amp;gt;= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個字串s跟一個字串t，&lt;br>
檢查s是否是t的subsequence(子序列)。可以假設s是一個短字串(長度≤100)且t是一個長字串(長度約500000)。&lt;/p>
&lt;p>從原字串t刪除字母(也可以完全不刪)，&lt;br>
並保有原字串的相對位置，所構成的新字串，即為t的子序列。&lt;br>
後面有一個Follow up問的是，&lt;br>
假設這個函式會拿來檢查很多次(k次)不同的S的話(例如會處理1billion次)，&lt;br>
要怎麼實作這個函式比較好？&lt;/p>
&lt;p>首先我們先來看看比較直觀的解法。&lt;br>
我們先舉個例子，如果有一個s是”abcde”的話，&lt;br>
s要是t的子序列的條件，就是我們要能在t當中，&lt;br>
&lt;strong>依序得到&lt;/strong> a~e這五個字母。&lt;br>
那麼第一個我們一定要先找a，假設從t中找到一個a以後，&lt;br>
按照順序的話，&lt;strong>這個a以前的bcde就都不能用了&lt;/strong> ！&lt;br>
(因為順序就不對啦XD)&lt;br>
同樣的，找到b以後b以前的cde也不能用，以此類推。&lt;br>
因此，我們要保持能確定找到可能性的方式，&lt;br>
就是&lt;strong>每一次在t中都取這個順序最前面出現的字母&lt;/strong> 。&lt;/p>
&lt;p>在s當中使用一個記錄index用的&lt;strong>i&lt;/strong> ，&lt;br>
從頭開始&lt;strong>找t中的s[i]&lt;/strong> 在哪，記錄為&lt;strong>pre&lt;/strong> 。&lt;br>
每次找到以後，&lt;strong>將i遞增&lt;/strong> ，&lt;br>
接下來從&lt;strong>t的pre+1處&lt;/strong> 開始尋找下一個s[i]的位置。&lt;br>
如果找不到的話呢？就表示沒辦法成立，應該回傳false，&lt;br>
否則當全部的s的字母都能找到對應的位置的話，&lt;br>
則代表s可以作為t的子序列。&lt;/p>
&lt;p>上面描述這樣的方法，我們使用了兩個索引值，&lt;br>
來記錄s和t當前查找到的位置，&lt;br>
所以這個解法可以視為two pointer手段的一種操作。&lt;/p>
&lt;p>同時，我們前面在解的時候，&lt;br>
每次都&lt;strong>盡可能&lt;/strong> 去找&lt;strong>最前面出現&lt;/strong> 的第一個s[i]，&lt;br>
這種概念的想法，僅在特定的題目適用。&lt;br>
當符合在&lt;strong>每一個當前狀況都取當前最佳的狀況&lt;/strong> ，&lt;br>
&lt;strong>全局就會是最佳&lt;/strong> 的時候，我們就在局部的區段盡可能貪婪。&lt;br>
這樣子的策略被稱為&lt;strong>貪婪演算法&lt;/strong> (Greedy Algorithm)&lt;/p>
&lt;p>請留意到，這種方式往往在很多情況下會失效，&lt;br>
所以在使用前請詳閱公開說明書(X)。&lt;br>
(開玩笑的XD，應該是&lt;strong>使用前請確認局部最佳能推導至全局最佳&lt;/strong> 。)&lt;/p>
&lt;p>這麼做基本上要掃過s跟t的字串，所以時間會是O(len(s)+len(t))，&lt;br>
或者說當t遠大於s的時候可以視為O(len(t))。&lt;/p>
&lt;p>那麼如果搭配Follow up的條件呢？&lt;br>
如果有k次不同的s的檢查，&lt;br>
就上面的解法而言，每次仍然要各掃過一遍s跟t，&lt;br>
時間複雜度是&lt;strong>O(k*(len(s)+len(t)))&lt;/strong> ，顯然當t很大的時候，&lt;br>
掃過k次是很不理想的，我們會希望能夠化簡一點這個部分。&lt;/p>
&lt;p>那要怎麼作呢？這邊引用&lt;strong>shuoshankou&lt;/strong> 在leetcode上的解，&lt;br>
我們可以先&lt;strong>針對t建立一個HashMap&lt;/strong> ，當中的&lt;strong>key是t上的字母&lt;/strong> ，&lt;br>
而&lt;strong>value是這個字母出現在t上面的indices&lt;/strong> (使用ArrayList來儲存)。&lt;br>
這個儲存過程會是&lt;strong>O(len(t))&lt;/strong> 。&lt;/p>
&lt;p>接著要查找的過程就會變成&lt;strong>針對s[i]來搜尋HashMap上的index，&lt;br>
且限定這個index要剛好是在i之後的第一個出現的位置。&lt;strong>有沒有覺得很眼熟？沒錯，&lt;/strong> 這不就是Binary Search嗎&lt;/strong>？&lt;br>
我們在處理的，就跟對於某個陣列，&lt;br>
搜尋一個值在哪裡(或應插入在哪裡)的問題一樣！&lt;/p>
&lt;p>所以就一般來說，搜尋需求是log(N)，&lt;br>
如果前後拆成常數的單位可以忽略不記，&lt;br>
所以對於k個s搜尋所需會是&lt;strong>O(k*len(s) * log(len(t)))&lt;/strong> ，&lt;br>
當k大到一定程度的時候，顯然只作一次O(len(t))先建立對應表，&lt;br>
讓後面的&lt;strong>搜尋相關的t的複雜度都變成對數量級&lt;/strong> 是相當划算的。&lt;/p>
&lt;p>注意，以這題的測試資料而言，Binary Search速度並不會跑起來比較漂亮，&lt;br>
原因是測試資料的總數可能相對有限，並不像Follow up假想那樣，&lt;br>
所以前面吃下一整個建立HashMap的時間就會顯得拖累。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分可以先檢查s和t的長度來避免一些根本不需要跑的狀況，&lt;br>
同時使用&lt;strong>indexOf&lt;/strong> 來搜尋每次的si第一個出現的位置。&lt;br>
(&lt;strong>搜尋不到的話indexOf會回傳-1&lt;/strong> )&lt;/p>
&lt;p>Binary Search的寫法則如註解處，&lt;br>
先建立起HashMap並掃過整個t並依序塞入，&lt;br>
後面再使用getNextIndex來寫Binary Search。&lt;br>
其實如果要能像Follow up那樣反覆利用的話，&lt;br>
應該要能將t的輸入抽離開來，題目的要求和預設寫法並沒有考慮這點，&lt;br>
會導致每次都需要對t建立一個HashMap。&lt;/p>
&lt;p>如果要重複利用的話，應該要給定成class Solution的變數，&lt;br>
且建立時能先給入t才對。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/455f2c972c9c7f23ac66c831e013cd03.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分則使用&lt;strong>index&lt;/strong> 來進行查找，&lt;br>
請留意查找不到的話會產生exception，&lt;br>
所以這邊是使用&lt;strong>try/except&lt;/strong> 來處理的。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/075cf41436103c259d2b37f3bccd4c41.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(請見上面詳述。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(接下來快要漲成下個價格啦XD)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=VEQZV7E&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 77 String (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-77-string-2/</link><pubDate>Tue, 24 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-77-string-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 77 String (2)" />&lt;p>&lt;strong>1071. Greatest Common Divisor of Strings (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>For strings &lt;code>S&lt;/code> and &lt;code>T&lt;/code>, we say &amp;ldquo;&lt;code>T&lt;/code> divides &lt;code>S&lt;/code>&amp;rdquo; if and only if &lt;code>S = T + ... + T&lt;/code> (&lt;code>T&lt;/code> concatenated with itself 1 or more times)&lt;/p>
&lt;p>Return the largest string &lt;code>X&lt;/code> such that &lt;code>X&lt;/code> divides str1 and &lt;code>X&lt;/code> divides str2.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: str1 = &amp;#34;ABCABC&amp;#34;, str2 = &amp;#34;ABC&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;ABC&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: str1 = &amp;#34;ABABAB&amp;#34;, str2 = &amp;#34;ABAB&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;AB&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: str1 = &amp;#34;LEET&amp;#34;, str2 = &amp;#34;CODE&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>1 &amp;lt;= str1.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= str2.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>str1[i]&lt;/code> and &lt;code>str2[i]&lt;/code> are English uppercase letters.&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩字串，找出能「除盡」這兩個字串的最長字串X。&lt;br>
題目已經給定的非常明顯了就是在求gcd(最大公因數)，&lt;br>
因此，拿出小學就教過的輾轉相除法即可。&lt;br>
(要看起來厲害一點的話，也可以叫歐幾里得算法Euclidean algorithm)&lt;/p>
&lt;p>輾轉相除法告訴我們說，兩個數的最大公因數，&lt;br>
就是不斷將大的除以小的，取出餘數替代之，直到能夠整除為止。&lt;br>
於是這邊變成字串時，我們的除就會比較麻煩一點。&lt;br>
為求簡單起見，我們可以&lt;strong>固定將第一個字串選擇放比較長的&lt;/strong> ，&lt;br>
如果&lt;strong>發現相反&lt;/strong> 的話，則將&lt;strong>兩者進行對調&lt;/strong> 。&lt;/p>
&lt;p>所以就可以分成以下的步驟：&lt;/p>
&lt;ol>
&lt;li>取兩字串長l1, l2，若&lt;strong>l1 &amp;lt; l2&lt;/strong> 則呼叫遞迴&lt;strong>將str1, str2交換&lt;/strong>&lt;/li>
&lt;li>若&lt;strong>str1和str2完全一樣，則回傳str1&lt;/strong>&lt;/li>
&lt;li>若&lt;strong>str1的前面的部分&lt;/strong> 和&lt;strong>str2&lt;/strong> 一樣，則將&lt;strong>str1扣除掉該部份&lt;/strong> 以後，&lt;br>
呼叫遞迴傳入繼續計算。&lt;br>
(因為我們&lt;strong>操作字串的除只能一組一組扣掉&lt;/strong> )&lt;/li>
&lt;li>&lt;strong>否則就回傳空字串&lt;/strong> (因為不一樣的話代表完全沒有共同的字串，&lt;br>
跟數字的最大公因數是1概念一樣)&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，字串相等請使用equals來比較，&lt;br>
而前面的部分一樣可以用startsWith函式，&lt;br>
並留意空字串要用雙引號，不能用單引號(因為單引號是char)。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/f9c0aac5ec9fcf7cbfe93a3080581a98.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，使用==和串列取值的方式，&lt;br>
可以簡單達成我們所需要的操作。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e10ef7464eda8e4eba004dcbf086cde7.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(l1+l2)/O(l1+l2)，由於每階段會固定消去最小單位的長度，&lt;br>
所以最差的狀況就是全部都消去，也就做了兩字串長度的消去的動作，&lt;br>
但中間未考慮比較是否相等的狀況。&lt;br>
空間複雜度的部分，&lt;br>
Java的substring和Python的切list的方式都會產生新的單位，&lt;br>
理論上仍然最少會佔用到完整的l1+l2單位空間)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=VEQZV7E&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 76 Hash Table (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-76-hash-table-5/</link><pubDate>Sat, 21 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-76-hash-table-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 76 Hash Table (5)" />&lt;p>&lt;strong>0290. Word Pattern (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a &lt;code>pattern&lt;/code> and a string &lt;code>str&lt;/code>, find if &lt;code>str&lt;/code> follows the same pattern.&lt;/p>
&lt;p>Here &lt;strong>follow&lt;/strong> means a full match, such that there is a bijection between a letter in &lt;code>pattern&lt;/code> and a ** non-empty** word in &lt;code>str&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: pattern = &amp;#34;abba&amp;#34;, str = &amp;#34;dog cat cat dog&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:pattern = &amp;#34;abba&amp;#34;, str = &amp;#34;dog cat cat fish&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: pattern = &amp;#34;aaaa&amp;#34;, str = &amp;#34;dog cat cat dog&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: pattern = &amp;#34;abba&amp;#34;, str = &amp;#34;dog dog dog dog&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Notes:&lt;/strong>&lt;br>
You may assume &lt;code>pattern&lt;/code> contains only lowercase letters, and &lt;code>str&lt;/code> contains lowercase letters that may be separated by a single space.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個pattern和一個字串str，檢查str是否遵循pattern的模式。&lt;br>
簡單來說，就是str的每一段字的重複或不重複模式，&lt;br>
都要能被pattern裡的&amp;quot;abba&amp;quot;這樣的&lt;strong>每個字母去對應&lt;/strong> 的方式來表達出來。&lt;br>
看到這邊，有沒有覺得很像LeetCode最開始的那個&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-1-400da76b51b4" target="_blank" rel="noopener"
>Two Sum&lt;/a>?&lt;br>
我們每次想要將一個pattern內的字母去對應到str的一段字串，&lt;br>
而重複的狀況應該要有相同的對應。&lt;/p>
&lt;p>&lt;strong>那不就是key-value的對應方式嗎?&lt;/strong>&lt;/p>
&lt;p>所以想法就很簡單了：&lt;/p>
&lt;ol>
&lt;li>建立一個Hash Table名為map(Java的HashMap或Python的Dictionary)&lt;/li>
&lt;li>先檢查&lt;strong>pattern的段數和str的段數是否相同&lt;/strong> ，&lt;strong>若否則直接回傳false&lt;/strong>&lt;/li>
&lt;li>&lt;strong>依序按段取出&lt;/strong> pattern和對應的str的分段，檢查以下性質：&lt;br>
&lt;strong>(下面pattern均作為key，str的分段均作為value)&lt;/strong>&lt;br>
若key不存在且value不存在-&amp;gt;將**(key, value)** 放入map&lt;br>
若key不存在且value存在-&amp;gt;回傳&lt;strong>false&lt;/strong> (** 表示別人先對應到它了**)&lt;br>
若key存在且value不對-&amp;gt;回傳&lt;strong>false&lt;/strong> (** 表示該key已經被占用掉**)&lt;/li>
&lt;/ol>
&lt;p>請留意後面的兩個false的狀況，&lt;br>
我們可以對照&lt;strong>Example 2&lt;/strong> 跟&lt;strong>Example 3&lt;/strong> ，&lt;br>
因為有些可能是前面某個key或某個value已經達成對應關係了，&lt;br>
後續如果出現對不上的狀況，就表示整個對應關係無法成立囉！&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，&lt;br>
可以使用HashMap的containsKey/containsValue/get，&lt;br>
以及字串的split/equals函式，來協助判斷的工作。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/8f30742455b74157505537e719e1f9ab.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python方面，同樣有split可以使用，&lt;br>
其他使用dict的in/not in及values()等簡單的存取方式即可。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/409bf9bf6b7863af7302c72a4825e032.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，準確來說應該是看len(str)來決定N)&lt;/p>
&lt;p>「如果限制使用split呢？」&lt;br>
(進行依字元掃瞄過整個陣列，碰到空白再輸出成字串(list或arraylist)即可)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>** https://hiskio.com/courses/319?promo_code=VEQZV7E**&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 75 Array (14)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-75-array-14/</link><pubDate>Thu, 19 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-75-array-14/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 75 Array (14)" />&lt;p>&lt;strong>0289. Game of Life (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>According to the &lt;a class="link" href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" target="_blank" rel="noopener"
>Wikipedia’s article&lt;/a>: “The &lt;strong>Game of Life&lt;/strong> , also known simply as &lt;strong>Life&lt;/strong> , is a cellular automaton devised by the British mathematician John Horton Conway in 1970.”&lt;/p>
&lt;p>Given a &lt;em>board&lt;/em> with &lt;em>m&lt;/em> by &lt;em>n&lt;/em> cells, each cell has an initial state &lt;em>live&lt;/em> (1) or &lt;em>dead&lt;/em> (0). Each cell interacts with its &lt;a class="link" href="https://en.wikipedia.org/wiki/Moore_neighborhood" target="_blank" rel="noopener"
>eight neighbors&lt;/a> (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):&lt;/p>
&lt;ol>
&lt;li>Any live cell with fewer than two live neighbors dies, as if caused by under-population.&lt;/li>
&lt;li>Any live cell with two or three live neighbors lives on to the next generation.&lt;/li>
&lt;li>Any live cell with more than three live neighbors dies, as if by over-population..&lt;/li>
&lt;li>Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.&lt;/li>
&lt;/ol>
&lt;p>Write a function to compute the next state (after one update) of the board given its current state. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,1,0],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,0,1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,1,1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,0,0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,0,0],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,0,1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,1,1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,1,0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up&lt;/strong> :&lt;/p>
&lt;ol>
&lt;li>Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.&lt;/li>
&lt;li>In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>這題是典型的&lt;a class="link" href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" target="_blank" rel="noopener"
>&lt;strong>生命遊戲&lt;/strong> &lt;/a>題目。生命遊戲一般是透過2D的棋盤式的格子，&lt;br>
上面以1代表活著的細胞，0代表死去的細胞，&lt;br>
透過設定好的規則來觀察其演化的狀況。&lt;br>
設定這些東西的目的最初應該是為了要產生模擬圖靈機，&lt;br>
後來發現一些有趣的現象，比如能穩定周期性的圖案像是滑翔機、&lt;br>
機關槍等等，也有的看似是有周期的但最後會消滅的狀況，&lt;br>
總之某種層面上有點像是可以拿來模擬族群聚落的演進等狀態就是了，&lt;br>
有興趣的讀者可以再看看相關的資料。&lt;/p>
&lt;p>回到題目，基本上生命遊戲裡面的每個單位，&lt;br>
在下一個時間點要嘛是1(活著)，不然就是0(死去)。&lt;br>
典型的規則是看其九宮格的周圍：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>如果原本自己是&lt;strong>1(活著)&lt;/strong> 的話，只有周圍有&lt;strong>2~3個&lt;/strong> 鄰居(活著的細胞)，&lt;br>
下一刻自己才會繼續存活，否則就會死去。&lt;br>
(&lt;strong>只有1個鄰居以下會因人口過少而死，&lt;br>
而超過3個鄰居會因人口過多而死&lt;/strong>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果原本自己是&lt;strong>0(死去)&lt;/strong> 的話，只有周圍&lt;strong>恰好有3個鄰居&lt;/strong> ，&lt;br>
下一刻自己會變成&lt;strong>1(活著)&lt;/strong> (視作被繁衍出來的後代)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Follow up有兩點，1是詢問是否能in-place解題，&lt;br>
2是棋盤是無窮大的話該怎麼描述問題。&lt;/p>
&lt;p>這個題目其實看懂定義的話並不困難，只是繁瑣而已。&lt;br>
首先有一個重點是：更新的時候必須要一口氣一起更新，&lt;br>
因為每個細胞的變化都需要看周圍的細胞，不同時改變的話，&lt;br>
結果就有可能會出錯。這邊有兩種考慮方式：&lt;/p>
&lt;ol>
&lt;li>開一個跟board一樣大的二維陣列(串列)，&lt;br>
記錄下一刻的狀態，最後再進行替換。&lt;/li>
&lt;li>想辦法&lt;strong>用原有的board&lt;/strong> 來進行記錄。&lt;br>
我們這邊因為希望達成in-place，所以自然選擇2。&lt;br>
還記得之前我們提過的word search嗎？&lt;br>
我們利用了沒有被用到的位元做為遮罩進行XOR，&lt;br>
使得visited的資訊用原先的棋盤就可以做記錄了；&lt;br>
這邊比之前還要簡單，我們只要拿&lt;strong>2的1次方位&lt;/strong> 來記錄即可，&lt;br>
因為&lt;strong>board一開始只用到1和0而已&lt;/strong> ，所以判斷完以後，&lt;br>
&lt;strong>如果它會變成存活的狀態，則將該值加上2，&lt;/strong>&lt;br>
&lt;strong>死去的話則不用額外動作。&lt;/strong>&lt;br>
這樣一來，最後我們只要&lt;strong>將整個board除以2取整數&lt;/strong> ，&lt;br>
就可以得到新的棋盤狀態了！&lt;br>
中間在進行周圍八格的判斷時，不要忘記要&lt;strong>除以2取餘數&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>所以總體會像這樣：&lt;/p>
&lt;ol>
&lt;li>遍歷整個棋盤做check&lt;/li>
&lt;li>&lt;strong>check&lt;/strong> 函式中:&lt;br>
 a. 依次檢查是否存活(alive)，並&lt;strong>加總&lt;/strong> 周圍八格的存活細胞數量&lt;br>
 b. 若&lt;strong>本身當前存活&lt;/strong> -&amp;gt; 檢查** 周圍存活數&lt;strong>是&lt;/strong> 2或3&lt;strong>時，&lt;/strong> 將自己加上2**&lt;br>
 c. 否則(&lt;strong>本身死亡&lt;/strong> )，若&lt;strong>周圍存活數&lt;/strong> 是&lt;strong>3&lt;/strong> ，&lt;strong>將自己加上2&lt;/strong>&lt;/li>
&lt;li>&lt;strong>alive&lt;/strong> 函式中:&lt;br>
 a. 若&lt;strong>超出邊界則回傳0&lt;/strong>&lt;br>
 b. 否則回傳&lt;strong>該格數值除以2的餘數&lt;/strong>&lt;/li>
&lt;li>全數檢查完後呼叫&lt;strong>next&lt;/strong> 函式更新狀態&lt;/li>
&lt;li>&lt;strong>next&lt;/strong> 函式: 遍歷整個棋盤，將&lt;strong>值除以2取整數&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>一般典型的話理論上邊界應該要互相連接，&lt;br>
(走到最底會通往最上面，走到最右邊會連通最左邊)&lt;br>
但我們這邊就不考慮這個問題了。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分，計算八方向我們使用了一個d(direction)的二維陣列來記錄，&lt;br>
除了邊界條件以外沒有特別需要注意的地方。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/96f31a039e6bc3b800de6d439bbc3b0a.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分，d的方面我們可以用&lt;strong>list comprehension&lt;/strong> ，&lt;br>
扣掉自身(0, 0)來建構。除了留意子函式的定義，&lt;br>
要在拿來做為&lt;strong>global的部分後面(才能拿來用)&lt;/strong> ，&lt;br>
在&lt;strong>呼叫之前(因為是腳本執行)&lt;/strong> 以外，&lt;br>
其他沒有什麼特別的地方XD&lt;/p>
&lt;script src="https://gist.github.com/Desolve/db3c16998ccc01aadab7d7ccd8f9687d.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(m * n), O(1))&lt;/p>
&lt;p>「如果棋盤無限大？」&lt;br>
(那應該要找出一個pattern來表示它才對，&lt;br>
不可能真的開出一個無限大的棋盤)&lt;/p>
&lt;p>「首尾相接的話？」&lt;br>
(Python直接按照負數index會發生的事情處理，&lt;br>
Java要自己計算過界的狀況)&lt;/p>
&lt;p>「還能簡化嗎？」&lt;br>
(理論上相鄰的兩個點會&lt;strong>共用到4個鄰居點&lt;/strong> ，&lt;br>
應該可以再節省一點計算時間，&lt;strong>但時間複雜度是一樣的&lt;/strong> )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>第二階段Medium優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
>https://hiskio.com/courses/319?promo_code=VEQZV7E&lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 74 Linked List (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-74-linked-list-8/</link><pubDate>Mon, 16 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-74-linked-list-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 74 Linked List (8)" />&lt;p>&lt;strong>0234. Palindrome Linked List (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a singly linked list, determine if it is a palindrome.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;2-&amp;gt;1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;br>
Could you do it in O(n) time and O(1) space?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個單向鏈結串列，試判斷它是否是palindrome(回文)。&lt;br>
所謂palindrome就是&lt;strong>從尾到頭和從頭到尾看起來會相同&lt;/strong> 。&lt;br>
在這題當中，由於我們的結構是Linked List，無法很輕鬆的到達尾端，&lt;br>
也無法輕易的回頭，那麼該怎麼辦呢？&lt;br>
要判斷回文有一個重點，就是&lt;strong>從中間切開來兩邊是對稱的&lt;/strong> 。&lt;br>
因此，我們可以設定fast/slow的兩個pointer，&lt;br>
以之前常用的技巧，&lt;strong>每次fast走兩步，slow走一步&lt;/strong> ；&lt;br>
&lt;strong>讓fast走到底時，slow剛好走到一半&lt;/strong> 。&lt;br>
節點總數是偶數時，切開來的第二段應該是從&lt;strong>slow的下一個節點&lt;/strong> 開始，&lt;br>
所以&lt;strong>當fast不是NIL&lt;/strong> 時，我們應該&lt;strong>讓slow多走一步&lt;/strong> 。&lt;br>
(例如總共有10個節點，按上面的方法走完，&lt;br>
fast會在10，slow會在5，但第二段應該從6開始，所以slow要往下走一步)&lt;/p>
&lt;p>所以比較「&lt;strong>從slow到串列尾端的反轉串列&lt;/strong> 」及&lt;br>
「&lt;strong>從head往下的對應節點&lt;/strong> 」，即可檢驗串列是否為回文。&lt;/p>
&lt;p>那麼要怎麼反轉串列呢？&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-72-linked-list-7-419253aa3a9a" target="_blank" rel="noopener"
>&lt;strong>上上篇文章&lt;/strong> &lt;/a>不就是嗎XD&lt;br>
我們可以用之前的reverse函數進行反轉，&lt;br>
反轉後再對兩個串列一一進行比較，&lt;br>
一旦值不相等即回傳false。&lt;/p>
&lt;p>依此，寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/6be1259696a5d491b8f8577daac86c53.js">&lt;/script>
&lt;p>我們也可以使用另一種思路，&lt;br>
先多設定一個rev節點，&lt;br>
在slow/fast行進時，將slow經過節點進行反轉連接，&lt;br>
這樣在走完的時候，讓&lt;strong>rev&lt;/strong> 變成&lt;strong>前半段反轉後的串列的開頭&lt;/strong> ，&lt;br>
而&lt;strong>slow&lt;/strong> 則是&lt;strong>後半段的串列的開頭&lt;/strong> 。最後同樣一個一個檢查，&lt;br>
即可判斷整個串列是否是回文。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4e3c298a79a619e991c7abdcb75bad36.js">&lt;/script>
&lt;p>務必請留意這麼做的缺點是&lt;strong>整個串列就被我們拆成兩半了&lt;/strong> ，&lt;br>
如果不是要求空間複雜度是O(1)的話，&lt;br>
用別的資料結構輔助去存入一半的節點，能夠保有原先的結構。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1))&lt;/p>
&lt;p>「如果不計較空間複雜度，有沒有辦法保留原先的linked list呢？」&lt;br>
(Python的話可以使用list來做兩邊儲存比較的動作，&lt;br>
或者要使用stack來置入前半段的節點，後面pop出來做比較也可以)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium限額5名優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9NJQE" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=VE9NJQE&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 73 Trie (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-73-trie-2/</link><pubDate>Mon, 09 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-73-trie-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 73 Trie (2)" />&lt;p>&lt;strong>0208. Implement Trie (Prefix Tree) (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Implement a trie with &lt;code>insert&lt;/code>, &lt;code>search&lt;/code>, and &lt;code>startsWith&lt;/code> methods.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Trie trie = new Trie();
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>trie.insert(&amp;#34;apple&amp;#34;);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trie.search(&amp;#34;apple&amp;#34;); // returns true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trie.search(&amp;#34;app&amp;#34;); // returns false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trie.startsWith(&amp;#34;app&amp;#34;); // returns true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trie.insert(&amp;#34;app&amp;#34;);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trie.search(&amp;#34;app&amp;#34;); // returns true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>You may assume that all inputs are consist of lowercase letters &lt;code>a-z&lt;/code>.&lt;/li>
&lt;li>All inputs are guaranteed to be non-empty strings.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>試實作一個trie，當中包含插入，搜尋，是否含前綴判斷的函式。&lt;/p>
&lt;p>我們很早以前&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-48-trie-1-533ffdfdc6ac?sk=26fa104e4af5aa5f8bbd986bb756a759" target="_blank" rel="noopener"
>講過一題使用Trie來進行解題的問題&lt;/a>，這次再來複習一下XD&lt;br>
Trie跟樹非常相像，通常用來作字典搜尋，所以又叫做&lt;strong>字典樹&lt;/strong> 。&lt;br>
在實作Trie的時候，我們通常會實作TrieNode作為每個節點的單位，&lt;br>
這當中每個節點主要會記錄兩件事：&lt;br>
&lt;strong>1. 這個節點是否到這邊構成一個字&lt;/strong>&lt;br>
因為可能是經過的節點，比如word -&amp;gt; w, o, r, d，&lt;br>
假設我們插入了一個這樣的字，那麼總共會生成4個節點，&lt;br>
但&lt;strong>只有d&lt;/strong> 這邊應該被判定到此&lt;strong>構成一個字&lt;/strong> 。&lt;br>
所以就這題而言，&lt;br>
我們可以使用一個boolean值(True/False)來儲存這個狀態，&lt;br>
也就是下面程式碼中看到的&lt;strong>isWord&lt;/strong> 。&lt;/p>
&lt;p>&lt;strong>2. 這個節點往下連接的節點群&lt;/strong>&lt;br>
以這題來說，由於僅限定a到z，所以我們其實可以用長度為26的節點陣列，&lt;br>
來表達下一個連結。當節點不存在時，表該路徑不存在/尚未生成，&lt;br>
在Java中我們用一個TrieNode[] next來儲存。&lt;/p>
&lt;p>但對Python而言，因為語言特性，&lt;br>
我們無法在TrieNode內直接宣告TrieNode(會報錯)，&lt;br>
所以會選擇使用一個字典進行記錄。&lt;/p>
&lt;p>最後，留意到由於我們每次進行路徑移動時，&lt;br>
所使用的index要嘛是&lt;strong>該字元減去’a’&lt;/strong> (Java)，&lt;br>
要嘛乾脆是&lt;strong>當前的字元&lt;/strong> (Python)，&lt;br>
&lt;strong>所以我們不需要額外耗費空間記錄字元值&lt;/strong> 。&lt;br>
此外，若題目有要求記錄被存入的相同字的次數，&lt;br>
就需要額外的count變數來儲存。(另外可以將isWord改成count用作判斷)&lt;/p>
&lt;p>所以整個的思路就會很明顯了：&lt;/p>
&lt;ol>
&lt;li>定義一個TrieNode class，當中有isWord跟next。&lt;/li>
&lt;li>在Trie中，初始化時宣告一個根節點root的TrieNode。&lt;/li>
&lt;li>insert: 節點從root處開始查找，沿著每個字元連接到下一個TrieNode，&lt;br>
並且如果節點尚未建立就將其建立，走到底後，將isWord設為true。&lt;/li>
&lt;li>search: 一樣從root開始，沿著每個字元往下走，&lt;br>
若碰到沒有建立則可直接回傳false。&lt;br>
當走到該節點以後，依據isWord的狀態來判斷要回傳true or false。&lt;/li>
&lt;li>startWith: 由於只要路過即可，所以前面和search一樣，&lt;br>
但最後只要能走到，即可回傳true。&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;p>Java的部分留意到使用了c - &amp;lsquo;a&amp;rsquo;的方式來取得index，&lt;br>
因為char是可以當作正整數來相減的。&lt;br>
TrieNode的建構式理論上可省略，&lt;br>
但直接先寫可以降低編譯器還要幫你生成的麻煩，&lt;br>
Submit實測上似乎平均會快一點點XD&lt;br>
(沒有大量測試，有興趣的讀者可再比較看看)&lt;br>
在最開頭的TrieNode代表著根，&lt;strong>但它本身並不代表任何字元&lt;/strong> ，&lt;br>
請留意這點。&lt;/p>
&lt;script src="https://gist.github.com/Desolve/3b966e6118553c20154031a162e3e551.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分額外提供了一個LeetCode上找到解答較快的版本，&lt;br>
是使用#的符號來取代isWord的功能，並用一個多層的字典名為tree，&lt;br>
來記錄整個字典樹的結構。&lt;br>
這個方法的好處是無需另外產生一個TrieNode的物件，&lt;br>
但缺點是&lt;strong>必須使用一個不會出現在字串中的符號&lt;/strong> 。&lt;br>
(如果今天這個字串內會含#的話，這個解就會無法使用了XD)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/b4e01ea397d5aa9c468a449fbbae5c17.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(插入：O(N)/空間全新的話O(N)&lt;br>
 搜尋：O(N)/O(1)&lt;br>
 前綴：O(N)/O(1)&lt;br>
 當中N代表字串長。)&lt;/p>
&lt;p>「如果要支援刪除呢？」&lt;br>
(要實作刪除函式時，不是使用TrieNode的話，&lt;br>
就要留意去處理自己製造的結束標記。&lt;br>
一般使用TrieNode很簡單，使用search找到該字，&lt;br>
並將isWord設成false/False即可。&lt;br>
記得詢問找不到該字要怎麼回傳。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium限額5名優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9NJQE" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=VE9NJQE&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 72 Linked List (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-72-linked-list-7/</link><pubDate>Mon, 02 Dec 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-72-linked-list-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 72 Linked List (7)" />&lt;p>&lt;strong>0206. Reverse Linked List (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Reverse a singly linked list.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;5-&amp;gt;NULL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5-&amp;gt;4-&amp;gt;3-&amp;gt;2-&amp;gt;1-&amp;gt;NULL
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>試反轉一個單向鏈結串列。&lt;br>
很久以前我們嘗試解過這題的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-12-linked-list-3-stack-1-f99d18e539a9" target="_blank" rel="noopener"
>較困難的版本&lt;/a>&lt;br>
(0092. Reverse Linked List II (Medium))，&lt;br>
不過是透過stack的輔助，這題較為簡單，&lt;br>
我們來嘗試不使用其他資料結構來試試看吧XD！&lt;/p>
&lt;p>先舉一個簡單的例子：&lt;br>
head -&amp;gt; a -&amp;gt; b -&amp;gt; c -&amp;gt; d -&amp;gt; &lt;strong>NIL&lt;/strong>&lt;br>
這個單向鏈結串列在反轉的時候應該會變成 ：&lt;br>
&lt;strong>NIL&lt;/strong> &amp;lt;- head &amp;lt;- a &amp;lt;- b &amp;lt;- c &amp;lt;- d&lt;/p>
&lt;p>我們可以先看head, a, b這段，&lt;br>
在反轉時，我們要將head的next從a改成別的指向；&lt;br>
但如果先改掉的話，那就喪失掉a的位置了，&lt;br>
所以我們需要一個tmp來記錄a的位置，&lt;br>
再將head的next指向到&lt;strong>前一個node&lt;/strong> (這邊一開始是NIL)，&lt;br>
最後讓tmp這個node做為下一個要處理的對象。&lt;br>
反覆處理，最終當head是null的時候，&lt;br>
回傳前一個node即為新的linked list的開頭(反轉前的尾端)。&lt;/p>
&lt;p>所以以迭代法的步驟上會像這樣：&lt;/p>
&lt;ol>
&lt;li>先宣告一個NIL的ListNode，我們命名為prev&lt;/li>
&lt;li>當head非null時，進行迴圈：&lt;br>
2-1. 宣告一個節點n，位置指定到head的位置&lt;br>
2-2. head往下走到其next&lt;br>
2-3. n的next位置指定成prev&lt;br>
2-4. 再將prev的位置指定到n&lt;/li>
&lt;li>迴圈完成後回傳prev即可&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>1. (prev=NIL) head -&amp;gt; a -&amp;gt; b ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>2. (n)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (prev=NIL) head -&amp;gt; a -&amp;gt; b ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>2-3 (head)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> prev=NIL &amp;lt;- n a -&amp;gt; b ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>2-4 NIL &amp;lt;- prev head=a -&amp;gt; b ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>以第一輪的迴圈推導會如上面，讀者也可以自行嘗試推演看看。&lt;/p>
&lt;p>若用遞迴的話也可以達到相同效果：&lt;/p>
&lt;ol>
&lt;li>呼叫一個遞迴函式rev，將(null, head)做為參數傳入&lt;br>
(在rev中，參數為前一個節點prev，跟當前的節點n)&lt;/li>
&lt;li>如果n為NIL的話則直接回傳prev&lt;/li>
&lt;li>宣告一個tmp節點，其位置指定為n.next&lt;/li>
&lt;li>再將n.next的位置指定給prev&lt;/li>
&lt;li>回傳rev(n, tmp)&lt;/li>
&lt;/ol>
&lt;p>所以不論哪一種方式，&lt;br>
我們基本上都是使用宣告的節點去記錄next的部分，&lt;br>
再將當前的節點的next指向到prev，從而完成將鏈結反向的工作。&lt;/p>
&lt;p>依此，寫成如下的程式碼：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/fe21838dc9ef718839d2b367d29ba70d.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/8206dc3b2d7f01acda91359968541054.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>Medium限額5名優惠(額滿即截止)：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VE9NJQE" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=VE9NJQE&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 71 Hash Table (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-71-hash-table-4/</link><pubDate>Tue, 26 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-71-hash-table-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 71 Hash Table (4)" />&lt;p>&lt;strong>0205. Isomorphic Strings (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two strings *&lt;strong>s&lt;/strong> * and *&lt;strong>t&lt;/strong> *, determine if they are isomorphic.&lt;/p>
&lt;p>Two strings are isomorphic if the characters in *&lt;strong>s&lt;/strong> * can be replaced to get *&lt;strong>t&lt;/strong> *.&lt;/p>
&lt;p>All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;egg&amp;#34;, t = &amp;#34;add&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;foo&amp;#34;, t = &amp;#34;bar&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;paper&amp;#34;, t = &amp;#34;title&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個字串s和t，試判斷它們是否同構(isomorphic)&lt;br>
若s和t同構，表示可以透過將s中的相同的字元轉換成另一個字元，&lt;br>
保有其順序，使得在轉換過後的s和t完全一樣。&lt;br>
&lt;strong>兩個不同的字元不可映射到相同的字元&lt;/strong> ，&lt;br>
但一個字元可以映射到原來的字元(也就是不變)。&lt;/p>
&lt;p>這個題目簡而言之，就是在找尋用特定方式轉換對應字的方法，&lt;br>
比如範例中的paper -&amp;gt; title有以下的轉換對應：&lt;br>
&lt;strong>p &amp;lt;-&amp;gt; t, a &amp;lt;-&amp;gt; i, e &amp;lt;-&amp;gt; l, r &amp;lt;-&amp;gt; e&lt;/strong>&lt;/p>
&lt;p>由於同構並沒有限制轉換方向，所以既要轉得過去，也要轉得回來，&lt;br>
這代表了他們對應必須要1對1才行。&lt;br>
因此，我們可以想到以下的方式：&lt;/p>
&lt;ol>
&lt;li>先檢查兩邊長度，不相等則直接回傳False (怎麼轉都沒用XD)&lt;/li>
&lt;li>可以選擇建立一個&lt;strong>HashMap/Dict&lt;/strong> 並&lt;strong>額外處理雙向&lt;/strong> 的對應檢查，&lt;br>
或者選擇開出&lt;strong>2個陣列/Dict(也可用串列，不過要自己轉換)&lt;/strong> 來做檢查。&lt;/li>
&lt;li>每次從s, t中&lt;strong>各取出一個字元&lt;/strong> (假設現在在&lt;strong>index i&lt;/strong> )：&lt;br>
3-1. 兩字元&lt;strong>都未進入&lt;/strong> 陣列對應 -&amp;gt; 將&lt;strong>s[i]&lt;/strong> 與&lt;strong>t[i]&lt;/strong> 放入兩個陣列的對應&lt;br>
3-2. 兩字元&lt;strong>都進入&lt;/strong> 陣列對應 -&amp;gt; 檢查&lt;strong>s[i]&lt;/strong> 是否對到&lt;strong>t[i]&lt;/strong> ，&lt;strong>t[i]&lt;/strong> 是否對到&lt;strong>s[i]&lt;/strong>&lt;br>
(只要&lt;strong>其中一個對錯或沒對到，即可判定為False&lt;/strong> )&lt;/li>
&lt;li>當所有字元均檢查完，表示順利全數對應到，回傳&lt;strong>True&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>簡單吧！&lt;br>
在Java的部份，&lt;br>
我們可以直接利用char可以自動轉換成int當作陣列的index。&lt;br>
沒有對應則會拿到預設值(0)，依此寫成以下程式碼：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/dbac3522b2153c0ab274cb73219cd3fa.js">&lt;/script>
&lt;p>Python的部份，方便起見我們使用了dict來紀錄，&lt;br>
預設值使用get放入0。&lt;/p>
&lt;p>另外提供一個特別的用法，可以使用&lt;strong>maketrans&lt;/strong> 及&lt;strong>translate&lt;/strong> ，&lt;br>
來進行兩個表的轉換。但由於中間可能有重複，&lt;br>
所以要先經過&lt;strong>set(刪去重複)和list, join&lt;/strong> 以後，&lt;br>
重新&lt;strong>依照原先的字母排列排序(用key＝s.index)&lt;/strong> ，&lt;br>
最終看看s經過轉換以後是否和t相同。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/679b5d53b4a16e6d36a878cdf5730a97.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N), 但空間複雜度最高取決於實際用到的字數，&lt;br>
亦可視為O(1)，因限縮在ASCII Code的話也才128種類)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>筆者開設的系列同名線上課程：&lt;br>
&lt;strong>「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong> 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>限額早鳥連結：&lt;/strong> &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=13L5QJE" target="_blank" rel="noopener"
>&lt;strong>https://hiskio.com/courses/319?promo_code=13L5QJE&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 70 Linked List (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-70-linked-list-6/</link><pubDate>Wed, 20 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-70-linked-list-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 70 Linked List (6)" />&lt;p>&lt;strong>0203. Remove Linked List Elements (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Remove all elements from a linked list of integers that have value *&lt;strong>val&lt;/strong> *.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;6-&amp;gt;3-&amp;gt;4-&amp;gt;5-&amp;gt;6, val = 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求將一個給定的linked list上值是val的所有元素均去除掉。&lt;/p>
&lt;p>前面已經講過一些linked list的題目了，&lt;br>
在處理的重點上，不外乎就是在於如何進行&lt;strong>遍歷&lt;/strong> ，&lt;br>
以及&lt;strong>移動&lt;/strong> 和&lt;strong>取代&lt;/strong> 的不同，是很多人容易弄混的。&lt;/p>
&lt;p>我們先假定有一組node的連結長這樣：&lt;br>
prev -&amp;gt; curr -&amp;gt; next&lt;/p>
&lt;p>今天如果想要遍歷的話，我們應該做的事情是先宣告一個node，&lt;br>
並將prev的位置指定給node：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Java:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ListNode node = prev;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>while (node != null) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> System.out.println(node.val);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node = node.next;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Python:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node = prev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>while node:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(node.val)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node = node.next
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這當中，node = node.next的方式變動了node所指向的記憶體位址，&lt;br>
使其切換到下一個(也就是curr所在的位址)，但&lt;strong>prev仍然在原地&lt;/strong> 。&lt;/p>
&lt;p>回歸到題目本身，&lt;br>
題目要求的是跳過特定的val值，例如1-&amp;gt;2-&amp;gt;6-&amp;gt;3，目標val是6。&lt;br>
遇到val值時，應該要&lt;strong>將2的連接從6改到3&lt;/strong> ，換言之，&lt;br>
當結點node走到2時，發現node.next.val跟目標val一樣，&lt;br>
連接上就會變成：&lt;br>
&lt;strong>node.next = node.next.next&lt;/strong>&lt;/p>
&lt;p>此外，為了要進行遍歷，所以每次node都需要往下一個前進，&lt;br>
在前一個狀況下已經確定了會將node.next接到node.next.next去了，&lt;br>
若val不同的話，則需要&lt;strong>將node的位置移到下一個&lt;/strong> 去：&lt;br>
&lt;strong>node = node.next&lt;/strong>&lt;/p>
&lt;p>還有一個問題，就是如果一開頭的値就符合val的話，&lt;br>
刪去頭會導致原先的head消失，&lt;br>
為了避免麻煩，常見的做法是宣告一個dummy node，將其連接到head處。&lt;br>
中間不論如何都不去動dummy，結尾時再將&lt;strong>dummy.next&lt;/strong> 回傳即可。&lt;/p>
&lt;p>Java的部分，我們初始化一個dummy node並另開一個curr來進行移動。&lt;br>
**每次curr.next的値符合時，就將curr.next接到curr.next.next，&lt;br>
否則就讓curr往下走。**這麼一來，只要不斷檢查curr.next是否為NIL並遞進即可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/f0cabb97c31bad564895f48456753d03.js">&lt;/script>
&lt;p>Python的部分大同小異。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/af26f72283e8e9d2c07ed134929ec03d.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/ O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>我將於&lt;strong>11/26&lt;/strong> 開設系列同名線上課程**「從Leetcode學演算法｜基礎篇」。** 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
&lt;strong>Leetcode解題挑戰拿優惠：&lt;/strong> &lt;a class="link" href="https://pse.is/NAUVP?fbclid=IwAR0g8Xi2wsWb8z2gWKgRGNz3HprupSc9MHbBCRnoXBaAEB7r3NNU8JiQXTc" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/NAUVP&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 69 Hash Set (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-69-hash-set-1/</link><pubDate>Tue, 19 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-69-hash-set-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 69 Hash Set (1)" />&lt;p>&lt;strong>0202. Happy Number (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write an algorithm to determine if a number is “happy”.&lt;/p>
&lt;p>A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 19
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1^2 + 9^2 = 82
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>8^2 + 2^2 = 68
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>6^2 + 8^2 = 100
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1^2 + 0^2 + 0^2 = 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個數，試檢查其是否為&lt;a class="link" href="https://en.wikipedia.org/wiki/Happy_number" target="_blank" rel="noopener"
>&lt;strong>快樂數(happy number)&lt;/strong> &lt;/a>。&lt;br>
所謂的快樂數就是從一個正整數n開始，將其每一個位數的平方和加總，&lt;br>
作為新的n值，反覆操作，若n最終等於1的話則為快樂數，&lt;br>
否則若n最終會進入一個不包含1的循環的話，則不是快樂數。&lt;/p>
&lt;p>之前我們介紹過HashTable(HashMap/Dictionary)，&lt;br>
&lt;strong>Java的HashSet和Python的set&lt;/strong> 其實是類似的概念，不過僅限於單值，&lt;br>
也就是說它們&lt;strong>每筆資料只存放一個值&lt;/strong> ，而非key/value相對。&lt;br>
一個Hash Set裡面，相同的值不能夠重覆出現，&lt;br>
同時利用了hash的性質，其&lt;strong>插入/查找&lt;/strong> 的速度也是&lt;strong>O(1)&lt;/strong> 。&lt;/p>
&lt;p>這題當中我們唯一需要考慮的問題就是當陷入循環的時候怎麼作判定，&lt;br>
所以我們可以使用Hash Set來進行記錄，當中若碰到n等於1的時候，&lt;br>
可以直接回傳true；其他狀況則&lt;strong>檢查n是否在Hash Set內&lt;/strong> ，&lt;br>
&lt;strong>若是，則表示已經碰到循環了，則可脫離迴圈回傳false&lt;/strong> 。&lt;/p>
&lt;p>在循環內計算下一個n基本上就是將除以10的餘數平方並移位後加總，&lt;br>
這邊就不再贅述。&lt;/p>
&lt;p>對Java而言，檢查是否在HashSet內請使用&lt;strong>contains()&lt;/strong> 。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/78093951c8e252cc611add2c0a233161.js">&lt;/script>
&lt;p>如果對快樂數有更進一步的認識的話，&lt;br>
當非快樂數陷入循環時會是固定的模式：&lt;br>
&lt;strong>4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4&lt;/strong>&lt;/p>
&lt;p>同時，&lt;strong>除了1和7以外，低於10的其他數均是非快樂數&lt;/strong> 。&lt;br>
所以也可以像上面寫到的另一種解法來處理這個問題，&lt;br>
在執行時間上對測試資料目前看起來是比較快的。&lt;/p>
&lt;p>對Python而言，使用in來檢查即可。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/bf9ff0122ec4a2f32f19a0a7674ffd5f.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(時間複雜度不確定，空間複雜度O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>這題也可以不使用HashSet/set來解，&lt;br>
請思考看看如果用two pointers的方式的話可以怎麼寫XD&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p>
&lt;p>我將於&lt;strong>11/26&lt;/strong> 開設系列同名線上課程**「從Leetcode學演算法｜基礎篇」。** 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br>
並實際完整練習&lt;strong>20題&lt;/strong> 精選考古題，&lt;br>
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br>
&lt;strong>問卷抽書＆取得上架通知：&lt;/strong> &lt;a class="link" href="https://pse.is/MS2J2?fbclid=IwAR2PMTGbMG-8qh2eq-kfGoolRWWYMPcEXdOa1Bib_pFFUaPlTlGb3UYAeDw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/MS2J2&lt;/strong> &lt;/a>&lt;br>
&lt;strong>Leetcode解題挑戰拿優惠：&lt;/strong> &lt;a class="link" href="https://pse.is/NAUVP?fbclid=IwAR0g8Xi2wsWb8z2gWKgRGNz3HprupSc9MHbBCRnoXBaAEB7r3NNU8JiQXTc" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/NAUVP&lt;/strong> &lt;/a>&lt;br>
如果你對線上課程不放心，&lt;br>
也可以先來&lt;strong>12/17(二)&lt;/strong> 我在天瓏分享的講座看看！&lt;br>
&lt;strong>講座連結：&lt;/strong> &lt;a class="link" href="https://pse.is/JS3LJ?fbclid=IwAR2j615ajqdqNsNHWTST4JnlCdbQzQecNaZG9LV7J55VFnw8ufLWojrk7iw" target="_blank" rel="noopener"
>&lt;strong>https://pse.is/JS3LJ&lt;/strong> &lt;/a>&lt;/p></description></item><item><title>從LeetCode學演算法 - 68 Bitwise Operation (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-68-bitwise-operation-5/</link><pubDate>Mon, 11 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-68-bitwise-operation-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 68 Bitwise Operation (5)" />&lt;p>&lt;strong>0201. Bitwise AND of Numbers Range (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a range [m, n] where 0 &amp;lt;= m &amp;lt;= n &amp;lt;= 2147483647, return the bitwise AND of all numbers in this range, inclusive.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [5,7]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [0,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個範圍m, n，且0≤m≤n≤2147483647(也就是2³¹-1)，&lt;br>
回傳這個範圍內(inclusive，即含n)的所有數字的bitwise AND的結果。&lt;/p>
&lt;p>首先這題要先理解inclusive表示&lt;strong>頭跟尾都要&lt;/strong> ，&lt;br>
例如[5, 7]，其範圍內的所有數字就是5, 6, 7。&lt;br>
再者如前面提到過的&lt;a class="link" href="https://medium.com/p/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-11-bitwise-operation-1-3117c4ce925d" target="_blank" rel="noopener"
>bitwise operation&lt;/a>的部份，&lt;br>
這邊做的是對每個bit一一對應做AND的操作。&lt;/p>
&lt;p>我們先來看一下範例1，將其化成二進位：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>5 : 101
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>6 : 110
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>7 : 111
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>AND : 100 =&amp;gt; Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>注意到由於AND操作要求&lt;strong>兩個bit都是1結果才是1&lt;/strong> ，&lt;br>
所以&lt;strong>中間一旦出現任意一個0的話，當個bit的AND結果最終必然是0&lt;/strong> 。&lt;br>
由於&lt;/p>
&lt;p>已經知道m≤n了，假設m跟n前面存在一組位元長得一模一樣，&lt;br>
例如：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>m: 100100101000 (2344)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>n: 100100111111 (2367)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>可以明顯看出從m到n的部份，&lt;strong>1001001&lt;/strong> 的位元是完全不變的，&lt;br>
&lt;strong>AND出來這部分顯然也會保留&lt;/strong> ，因為每個數字的這部份都一樣。&lt;/p>
&lt;p>那麼後面呢？&lt;br>
由於m ≤ n，&lt;br>
所以在後面不相同的狀況下，開始不相同的&lt;strong>m的第一個bit顯然會是0&lt;/strong> ，&lt;br>
&lt;strong>n的第一個bit顯然會是1&lt;/strong> ，那麼從m一路到n的bit變化，&lt;br>
就必然有從&lt;strong>011…1到100…0&lt;/strong> 的情況，&lt;br>
所以&lt;strong>後面的所有bit皆至少有出現過一次0&lt;/strong> ，&lt;br>
這會使得&lt;strong>後面的區塊經過AND完以後肯定是0&lt;/strong> 。&lt;/p>
&lt;p>所以整個問題就可以化簡成：&lt;br>
找到&lt;strong>m和n的最前面相同的bit，再將後面補上0即為答案&lt;/strong> 。&lt;/p>
&lt;p>要找這個很簡單，&lt;strong>每次檢查m, n是否相等，若否，&lt;br>
則各自向右移動一個bit&lt;/strong>，最終到** m, n相等&lt;strong>時，&lt;br>
只要乘上對應的位移倍數，即為解答。&lt;br>
讀者可以自行選用將factor視為&lt;/strong>位移位數** 或&lt;strong>必須相乘的倍數&lt;/strong> ，&lt;br>
兩者速度基本相似。&lt;/p>
&lt;p>除此之外還有另一個思路，既然我們只是想要n的前面那區bits，&lt;br>
那就一次從n剝離一個bit&lt;br>
( &lt;strong>n &amp;amp;= n-1&lt;/strong> , 先前的題目有提到可以用來一次去除最低位的bit)，&lt;br>
&lt;strong>直到n≤m為止。這時候留下來的n即為答案，因為低位的全被剝離了。&lt;/strong>&lt;/p>
&lt;p>依此，寫成程式碼。&lt;br>
(三者速度差異不大，但最後一種看起來最簡單，讀者可以自行斟酌選擇)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/5d6c0a6e95207e3dce83ebc163c05609.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/2ecc74f88ea1421b15bb4c0e11bd21bb.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n的長度)/O(1)，&lt;br>
因為要做到哪一步端看什麼時候找到m和n前面相同的位置)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 67 Bitwise Operation (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-67-bitwise-operation-4/</link><pubDate>Tue, 05 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-67-bitwise-operation-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 67 Bitwise Operation (4)" />&lt;p>&lt;strong>0191. Number of 1 Bits (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write a function that takes an unsigned integer and return the number of ‘1’ bits it has (also known as the &lt;a class="link" href="http://en.wikipedia.org/wiki/Hamming_weight" target="_blank" rel="noopener"
>Hamming weight&lt;/a>).&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 00000000000000000000000000001011
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The input binary string 00000000000000000000000000001011 has a total of three &amp;#39;1&amp;#39; bits.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 00000000000000000000000010000000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The input binary string 00000000000000000000000010000000 has a total of one &amp;#39;1&amp;#39; bit.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 11111111111111111111111111111101
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 31
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The input binary string 11111111111111111111111111111101 has a total of thirty one &amp;#39;1&amp;#39; bits.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Note that in some languages such as Java, there is no unsigned integer type. In this case, the input will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned.&lt;/li>
&lt;li>In Java, the compiler represents the signed integers using 2’s &lt;a class="link" href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank" rel="noopener"
>complement notation&lt;/a>. Therefore, in &lt;strong>Example 3&lt;/strong> above the input represents the signed integer &lt;code>-3&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個unsigned integer(正整數或0)，試回傳其位元為1的個數。&lt;/p>
&lt;p>這題其實比上一題還要再簡單一點XD&lt;br>
假設我們將數字稱為n，要計算其位元為1的個數的方式一般有兩個：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>看當前的位數是否為1&lt;/strong> 來決定是否遞增記錄累積的cnt(count)，&lt;br>
再將n向右位移1位，直到做完全部32個位元。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>將n每次和n-1相AND，可以去掉最低次的位元。&lt;/strong>&lt;br>
舉例來說：&lt;br>
n=11100 =&amp;gt; 11100 &amp;amp; 11011 = 11000&lt;br>
(減1時最低位的1會被借位，導致該位變成0，&lt;br>
其後的位數變成1，從而在相AND時全都會變成0)&lt;br>
n=10011 =&amp;gt; 10011 &amp;amp; 10010 = 10010&lt;br>
(最低位的1一開始就在最右邊，顯然減完最右邊變成0，&lt;br>
同樣會符合去掉最低次的位元的特性)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c4e1febe99301d694aeee82c77474182.js">&lt;/script>
&lt;p>Python的部份，也可以轉成二進位以後再用count去數'1&amp;rsquo;。&lt;br>
(不需要考慮前面的0b因為沒差XD)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/813fd4dc1b16e354c19a98f261d6c12e.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(1)/O(1)，因最多32次迴圈就結束了XD)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;/strong> 這題其實一樣可以有更精妙的解法，但同樣不建議在面試時使用。&lt;br>
(除非你要面試的就是非常在乎效能加速的公司)請參見JDK所使用的&lt;strong>Integer.bitCount()&lt;/strong> 函式原始碼講解：&lt;br>
&lt;a class="link" href="https://juejin.im/post/5c3969b76fb9a049a5712060" target="_blank" rel="noopener"
>https://juejin.im/post/5c3969b76fb9a049a5712060&lt;/a>&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 66 Bitwise Operation (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-66-bitwise-operation-3/</link><pubDate>Sat, 02 Nov 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-66-bitwise-operation-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 66 Bitwise Operation (3)" />&lt;p>&lt;strong>0190. Reverse Bits (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Reverse bits of a given 32 bits unsigned integer.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 00000010100101000001111010011100
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 00111001011110000010100101000000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 11111111111111111111111111111101
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 10111111111111111111111111111111
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10111111111111111111111111111111.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Note that in some languages such as Java, there is no unsigned integer type. In this case, both input and output will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned.&lt;/li>
&lt;li>In Java, the compiler represents the signed integers using 2’s &lt;a class="link" href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank" rel="noopener"
>complement notation&lt;/a>. Therefore, in &lt;strong>Example 2&lt;/strong> above the input represents the signed integer &lt;code>-3&lt;/code> and the output represents the signed integer &lt;code>-1073741825&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求將一個32bit長度的integer進行反轉。&lt;br>
(也就是將二進位制的各個bit 0變成1，1變成0)&lt;/p>
&lt;p>先前我們談過二進位的問題，以及一些&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-11-bitwise-operation-1-3117c4ce925d" target="_blank" rel="noopener"
>&lt;strong>位元運算&lt;/strong> &lt;/a>。&lt;br>
如果這題有要求處理正負號的問題的話，就會稍微複雜一點，&lt;br>
因為如題目提示的說明，Java中的有號的integer會使用**二補數&lt;br>
(2’s complement)**來表示，這件事情隱含了如果將bit位移時，&lt;br>
需要考慮是&amp;raquo;或&amp;raquo;&amp;gt;的問題。&lt;br>
&lt;strong>負數使用&amp;raquo;時最高位會補1，而&amp;raquo;&amp;gt;時最高位會補0&lt;/strong> ，&lt;br>
由於最高位用來記錄正負號，這會影響到實際得到的結果。&lt;/p>
&lt;p>但我們這邊單純只是要將整個32 bit順序反過來的話就沒有太大問題XD&lt;/p>
&lt;p>我們先從簡單一點的開始，&lt;br>
比如有一個數字n是1001100(也就是十進制的76)，&lt;br>
假設我們要將這7個bit反轉，應該要得到0011001，這個過程怎麼來的呢？&lt;/p>
&lt;p>先將我們的答案叫做r(result)，一開始為0，我們先這樣表示：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>r:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>n: 1001100
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>接下來我們要找下一個對應的bit的話，&lt;br>
n必須要取最右邊的bit才行，記錄完以後，&lt;br>
為了讓下一次的n的最右邊依然是我們要的bit，&lt;br>
可以將n進行一次向右位移，即可對到最右邊。&lt;br>
另外，r為了要記錄下一個位元，每次要向左位移一格，空出最右邊來。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>r: 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>n: 100110
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>重複相同的操作，直到n等於0或全部位元操作完畢即可。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>r: -&amp;gt; 0 -&amp;gt; 00 -&amp;gt; 001 -&amp;gt; 0011 -&amp;gt; 00110 -&amp;gt; 0011001
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>n:1001100 -&amp;gt; 100110 -&amp;gt; 10011 -&amp;gt; 1001 -&amp;gt; 100 -&amp;gt; 10 -&amp;gt; 1 -&amp;gt; 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>觀察上面的規律，我們可以歸納出對32位元的操作：&lt;br>
&lt;strong>1. 令res為0&lt;br>
2. 執行32次以下的迴圈：&lt;br>
2–1. res向左位移1位&lt;br>
2–2. 將n的最右邊的bit加到res上&lt;br>
2–3. 將n向右位移1位&lt;br>
3. 最終res即為答案&lt;/strong>&lt;/p>
&lt;p>依此，可以寫成如下的程式碼：&lt;br>
Java的部分，我們使用&amp;laquo;=和&amp;raquo;=進行各自位移後再回存。&lt;br>
而對應到2-2的部分，除了如第8行的寫法，&lt;br>
&lt;strong>將n和1進行AND運算&lt;/strong> 來確認&lt;strong>最右邊的位元&lt;/strong> 以外，&lt;br>
也可以用&lt;strong>AND完以後跟res進行OR&lt;/strong> 的方法。&lt;br>
此外，由於最開始res是0，&lt;br>
所以先將其往左位移一次是不會對答案造成影響的。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/df6aea77c9766e076286ff7e63040780.js">&lt;/script>
&lt;p>Python的部分提供一個看到比較特別的寫法：&lt;br>
使用format將n進行轉換，&lt;br>
當中0:032b的&lt;strong>第一個0可以不用寫&lt;/strong> (因為format中也只有一個數字)，&lt;br>
&lt;strong>第二個0代表多出來的部份必須進行補0&lt;/strong> (補完反轉才不會有問題)，&lt;br>
轉成32位的bit後，將其從尾往頭擺順序，&lt;br>
再用int轉換回integer(指定前面那段是二進制)即可。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/047e6a2806862ee268d066c9b5f74816.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，因為必然經過每個位元)&lt;/p>
&lt;p>「如果檢查n是否為0做為結束條件，執行速度是否會較快？」&lt;br>
(不一定，要看n反轉後的最接近高位的0有多接近，&lt;br>
否則每次多檢查一次未必比較快)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
From&lt;/strong> &lt;a class="link" href="https://www.facebook.com/groups/programmerMagazine/?ref=group_header" target="_blank" rel="noopener"
>** 程式人雜誌 — 公益出版**&lt;/a> ** - Novus Chou**:&lt;br>
「 &lt;strong>現實中比較講究的位元操作，會盡可能一次處理多位元，&lt;br>
而且最好不動用迴圈。&lt;/strong>&lt;/p>
&lt;p>以 8 bit 為例&lt;/p>
&lt;p>12345678&lt;br>
=&amp;gt; &lt;strong>21&lt;/strong> 436587 (奇偶交換)&lt;br>
=&amp;gt; 43&lt;strong>21&lt;/strong> 8765 (兩兩一組交換)&lt;br>
=&amp;gt; 8765&lt;strong>4321&lt;/strong> (前後半交換)&lt;/p>
&lt;p>類似 C 風格的寫法大概長這樣，&lt;br>
最後一輪利用整數自然截位所以不用 mask（當然這點要看語言特性）。&lt;/p>
&lt;p>x = (((x &amp;amp; 0xAA) &amp;raquo; 1) | ((x &amp;amp; 0x55) &amp;laquo; 1));&lt;br>
x = (((x &amp;amp; 0xCC) &amp;raquo; 2) | ((x &amp;amp; 0x33) &amp;laquo; 2));&lt;br>
x = (x &amp;raquo; 4) | (x &amp;laquo; 4);&lt;/p>
&lt;p>&lt;strong>更快的作法就是半查表，也就是把問題分解到某階段改用查的。&lt;/strong> 」&lt;br>
(註：利用連續的bit mask進行處理，可達到交換的目的，&lt;br>
這個方法對於&lt;strong>在意效能&lt;/strong> 來說，&lt;br>
由於&lt;strong>if/while/for&lt;/strong> 等&lt;strong>需要判斷&lt;/strong> 或&lt;strong>有分歧狀況&lt;/strong> 的程式碼，&lt;br>
皆須花費相對於位元運算而言&lt;strong>較多&lt;/strong> 的時間，&lt;br>
能夠單純利用位元運算達成互換會是在實際狀況較棒的解法。)&lt;/p>
&lt;p>(但，其實沒特別用過的話，面試時其實頗難回想出這種解法就是了XD)&lt;br>
&lt;strong>有興趣的話可以參考這兩篇：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;a class="link" href="https://leetcode.com/problems/reverse-bits/discuss/54741/O%281%29-bit-operation-C%2B%2B-solution-%288ms%29" target="_blank" rel="noopener"
>https://leetcode.com/problems/reverse-bits/discuss/54741/O(1)-bit-operation-C%2B%2B-solution-(8ms)&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a class="link" href="https://leetcode.com/problems/reverse-bits/discuss/54746/Java-Solution-and-Optimization" target="_blank" rel="noopener"
>https://leetcode.com/problems/reverse-bits/discuss/54746/Java-Solution-and-Optimization&lt;/a> &lt;strong>底下的&lt;/strong> &lt;a class="link" href="https://leetcode.com/dugu9sword" target="_blank" rel="noopener"
>** dugu9sword**&lt;/a> ** 的回應**&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>另外，Java中內建的&lt;strong>bitCount&lt;/strong> 函式(計算某個數的二進位制含有1的數量)，&lt;br>
也運用了類似的手法達到目的。&lt;br>
參見： &lt;a class="link" href="https://www.jishuwen.com/d/2HPI/zh-tw" target="_blank" rel="noopener"
>https://www.jishuwen.com/d/2HPI/zh-tw&lt;/a>&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>如果你／妳覺得這篇文章不錯，請給我5個Like。(點開SHOW EMBED!)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>從LeetCode學演算法 - 65 Array (13)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-65-array-13/</link><pubDate>Mon, 28 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-65-array-13/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 65 Array (13)" />&lt;p>&lt;strong>0926. Flip String to Monotone Increasing (Medium)&lt;/strong>&lt;/p>
&lt;ol start="926">
&lt;li>Flip String to Monotone Increasing (Easy)&lt;/li>
&lt;/ol>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>A string of &lt;code>'0'&lt;/code>s and &lt;code>'1'&lt;/code>s is &lt;em>monotone increasing&lt;/em> if it consists of some number of &lt;code>'0'&lt;/code>s (possibly 0), followed by some number of &lt;code>'1'&lt;/code>s (also possibly 0.)&lt;/p>
&lt;p>We are given a string &lt;code>S&lt;/code> of &lt;code>'0'&lt;/code>s and &lt;code>'1'&lt;/code>s, and we may flip any &lt;code>'0'&lt;/code> to a &lt;code>'1'&lt;/code> or a &lt;code>'1'&lt;/code> to a &lt;code>'0'&lt;/code>.&lt;/p>
&lt;p>Return the minimum number of flips to make &lt;code>S&lt;/code> monotone increasing.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;00110&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We flip the last digit to get 00111.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;010110&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We flip to get 011111, or alternatively 000111.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: &amp;#34;00011000&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We flip to get 00000000.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>一個只含'0&amp;rsquo;和'1&amp;rsquo;的字串在以下的狀況成立時會被視為&lt;strong>單調遞增&lt;/strong> ：&lt;br>
數個'0&amp;rsquo;作為開頭(也可能是0個)，其後接著數個'1&amp;rsquo;作為開頭(也可能是0個)。&lt;br>
(簡單說就是0後面接1就對了，也可以全0或全1)&lt;br>
給定一個字串&lt;strong>s&lt;/strong> ，且可以將當中任意的'0&amp;rsquo;翻轉成'1&amp;rsquo;，&lt;br>
也可以將任意的'1&amp;rsquo;翻轉成'0&amp;rsquo;，&lt;br>
試求要將s經過翻轉操作成為&lt;strong>單調遞增&lt;/strong> 的狀態所需的&lt;strong>最小翻轉次數&lt;/strong> 。&lt;/p>
&lt;p>這題其實某種程度隱含了一點動態規劃的概念在內，&lt;br>
但相對而言算是較簡單的。&lt;/p>
&lt;p>我們先思考根據單調遞增特性，由於這個特性，&lt;br>
注定了&lt;strong>一旦在某個點變為1，其後的每個單位也必須要是1&lt;/strong> 才可以。&lt;br>
若將最後的結果分成兩個狀況的話，事情會變比較簡單：&lt;/p>
&lt;ol>
&lt;li>全部都是0&lt;/li>
&lt;li>前面0後面1(含全部都是1)&lt;/li>
&lt;/ol>
&lt;p>考慮做到第i位時，要保持單調遞增所需翻轉的次數:&lt;br>
a. 如果第i位是0，對狀況1來說，不需額外作任何事情即可保持&lt;br>
b. 如果第i位是1，對狀況1來說，要將第i位翻轉為0(翻轉次數+1)&lt;br>
c. 如果第i位是0，對狀況2來說，要將第i位翻轉為1(翻轉次數+1)&lt;br>
d.如果第i位是1，對狀況2來說，相當於從第i-1位時選擇狀況1/狀況2均可&lt;/p>
&lt;p>若我們將上面的狀況1所需的翻轉次數叫做f0，&lt;br>
狀況2的所需次數叫做f1的話，&lt;br>
上面的&lt;strong>a/c就是第i位碰到'0&amp;rsquo;的狀況&lt;/strong> ，此時從&lt;strong>第i-1位的f0/f1&lt;/strong> 更新到&lt;strong>第i位&lt;/strong> 時，&lt;br>
&lt;strong>新的f0不需改變&lt;/strong> ，但&lt;strong>f1必須遞增&lt;/strong> ；&lt;br>
&lt;strong>b/d就是碰到'1&amp;rsquo;的狀況&lt;/strong> ，更新時&lt;strong>新的f1要取原先的f0, f1中較小的値&lt;/strong> ，&lt;br>
且&lt;strong>f0必須要遞增&lt;/strong> 。&lt;/p>
&lt;p>一開始什麼都還沒做，所以我們可以定&lt;strong>f0, f1均為0&lt;/strong> ，&lt;br>
接下來從頭到尾依照碰到的字元進行操作。&lt;/p>
&lt;p>最終，答案只要取&lt;strong>f0/f1中較小值&lt;/strong> 即可。&lt;/p>
&lt;p>依此寫成程式碼：&lt;br>
Java的部分可以利用for each的語法蜜糖來取出單個char，&lt;br>
(記得S要先轉成char array)&lt;br>
且需要留意&lt;strong>f0的遞增要在取完f1之後&lt;/strong> (不然值會錯)。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/95be0666e3bbfd9aa1755f3fdd02b8a4.js">&lt;/script>
&lt;p>Python的部分亦同，記得只有+=沒有++這種東西XD&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/fd557e6690a0eb852f4a78380769a26d.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，需遍歷整個String的長度，但記錄用輔助變數只需常數單位)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 64 Array (12) / Two Pointer (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-64-array-12-two-pointer-3/</link><pubDate>Tue, 22 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-64-array-12-two-pointer-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 64 Array (12) / Two Pointer (3)" />&lt;p>&lt;strong>0080. Remove Duplicates from Sorted Array II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a sorted array &lt;em>nums&lt;/em>, remove the duplicates &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
>&lt;strong>in-place&lt;/strong> &lt;/a> such that duplicates appeared at most &lt;em>twice&lt;/em> and return the new length.&lt;/p>
&lt;p>Do not allocate extra space for another array, you must do this by &lt;strong>modifying the input array&lt;/strong> &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
>** in-place**&lt;/a> with O(1) extra memory.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given nums = [1,1,1,2,2,3],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>It doesn&amp;#39;t matter what you leave beyond the returned length.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given nums = [0,0,1,1,1,1,2,3,3],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>It doesn&amp;#39;t matter what values are set beyond the returned length.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Clarification:&lt;/strong>&lt;/p>
&lt;p>Confused why the returned value is an integer but your answer is an array?&lt;/p>
&lt;p>Note that the input array is passed in by &lt;strong>reference&lt;/strong> , which means modification to the input array will be known to the caller as well.&lt;/p>
&lt;p>Internally you can think of this:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>// nums is passed in by reference. (i.e., without making a copy)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>int len = removeDuplicates(nums);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>// any modification to nums in your function would be known by the caller.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>// using the length returned by your function, it prints the first len elements.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>for (int i = 0; i &amp;lt; len; i++) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(nums[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個已排序的陣列nums，將其重復超過2次的部分捨棄掉，&lt;br>
且使用in-place的方式來操作(在原陣列操作)，回傳最終結果的長度。&lt;/p>
&lt;p>這題算是之前的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-10-linked-list-2-8384845e8ad6" target="_blank" rel="noopener"
>0083. Remove Duplicates from Sorted List (Easy)&lt;/a>的延伸，說真的我認為這題不該當作Medium難度XD&lt;/p>
&lt;p>再次提醒，當題目要求使用in-place的時候，&lt;br>
對一些語言的確是可以真的用&lt;strong>刪掉單點&lt;/strong> 的方式來處理(例如Python)，&lt;br>
但刪除這件事情也是較耗時的操作，所以沒特別要求的話，&lt;br>
請依照題目希望你的方向來撰寫(&lt;strong>面試則依照面試官的限制條件&lt;/strong> )。&lt;/p>
&lt;p>我們先來講筆者直觀想到的解法，再來提leetcode上另一位高手的解。&lt;/p>
&lt;p>直觀而言，要怎麼能夠知道有沒有碰到&lt;strong>3個&lt;/strong> 以上的重復呢？&lt;br>
最直接的方式就是使用一個cnt變數來記錄。&lt;br>
同時，為了要確認是否是重複的數，&lt;br>
我們需要記錄上一次開始重復的數last。&lt;/p>
&lt;p>那麼步驟就會像這樣：&lt;/p>
&lt;ol>
&lt;li>如果&lt;strong>nums長度 ≤ 2&lt;/strong> 的話，表示完全不用更動，&lt;br>
直接&lt;strong>回傳nums的長度&lt;/strong> 即可。&lt;/li>
&lt;li>將&lt;strong>last設為nums[0], cnt設為1,&lt;/strong> 預計要覆蓋的** index j設為1。**&lt;/li>
&lt;li>令i從1開始一個迴圈來遍歷整個nums:&lt;br>
3-a. 如果&lt;strong>nums[i]不等於last&lt;/strong> 的話，表示&lt;strong>數字不同&lt;/strong> ，&lt;br>
必須將其&lt;strong>覆蓋到j的位置&lt;/strong> 。&lt;br>
同時，我們必須更新&lt;strong>last為nums[i]，j要遞增，&lt;/strong>&lt;br>
&lt;strong>cnt要重設為1&lt;/strong> (用來做下一次比較)。&lt;br>
3-b. 否則，如果&lt;strong>兩者相等且cnt小於2&lt;/strong> ，&lt;br>
代表重複未超過2次，&lt;strong>同樣要進行複寫和遞增j，但cnt要遞增&lt;/strong> 。&lt;/li>
&lt;li>當整個迴圈完畢以後，&lt;strong>j&lt;/strong> 應該是位在&lt;strong>處理過後的陣列的尾端+1&lt;/strong> 的位置。&lt;br>
所以&lt;strong>回傳j即可代表新的陣列的總長&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>聽起來有點多，但其實寫起來並不困難，&lt;br>
但還有更厲害的解法XD&lt;/p>
&lt;p>這邊提供了LeetCode上&lt;strong>StefanPochmann&lt;/strong> 的解，&lt;br>
簡單來說呢，我們可以換個思路：&lt;br>
由於&lt;strong>整個陣列是排序過的&lt;/strong> ，當我們遍歷陣列時，&lt;br>
&lt;strong>某個數字應不應該要覆蓋到index上&lt;/strong> ，&lt;br>
(筆者之前的解法將這個index叫做j，相當於這個解裡的i)&lt;br>
取決於&lt;strong>前面兩個數字是否跟它一樣&lt;/strong> ；&lt;br>
都一樣的話，就產生了&lt;strong>三個相同的數&lt;/strong> 的狀況，&lt;br>
自然不需要再被取用，且由於排序的關係，&lt;br>
我們&lt;strong>只需要比較前面兩個數字中較前面的那個&lt;/strong> 即可。&lt;/p>
&lt;p>&lt;strong>當i小於2時，直接無條件覆蓋(&lt;/strong> 因為不可能重複超過2次)；&lt;br>
&lt;strong>當遍歷到的値n大於num[i-2]&lt;/strong> 時，代表&lt;strong>數字不一樣&lt;/strong> 或&lt;strong>重複未超過2次&lt;/strong> ，&lt;br>
則應&lt;strong>將其值覆蓋過去並遞增i&lt;/strong> 。&lt;/p>
&lt;p>各自寫成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/fccdca5faf3d5e8e4aac30bb83d61733.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9fa5e84db7919fbc222eaf5479cb23f1.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，我們需要遍歷整個陣列，且儲存用的輔助變數只有常數個)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 63 Backtracking (4) / DFS (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-63-backtracking-4-dfs-6/</link><pubDate>Fri, 18 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-63-backtracking-4-dfs-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 63 Backtracking (4) / DFS (6)" />&lt;p>&lt;strong>0077. Combinations (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two integers &lt;em>n&lt;/em> and &lt;em>k&lt;/em>, return all possible combinations of &lt;em>k&lt;/em> numbers out of 1 … &lt;em>n&lt;/em>.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: n = 4, k = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [2,4],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [3,4],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [2,3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,2],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,4],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個整數n跟k，回傳所有1~n之間取k個數字的組合。&lt;/p>
&lt;p>這題其實跟先前的&lt;a class="link" href="https://medium.com/@desolution/%e5%be%9eleetcode%e5%ad%b8%e6%bc%94%e7%ae%97%e6%b3%95-60-backtracking-3-dfs-5-ccc679dfa407" target="_blank" rel="noopener"
>0078. Subsets&lt;/a>非常的接近，&lt;br>
差別在於我們必須改成取得&lt;strong>固定k個&lt;/strong> ，&lt;br>
所以現在考慮上必須要將**「目前將取到第幾個數字」** 這件事情納入考量。&lt;/p>
&lt;p>那麼，我們可以同樣用&lt;strong>backtracking(回溯法)&lt;/strong> 的方式來考慮。&lt;br>
我們考慮初始化一個組合&lt;strong>combo&lt;/strong> ，從&lt;strong>1&lt;/strong> 開始決定要不要加入組合中，&lt;br>
&lt;strong>並記錄現在走到的index(以i表示)&lt;/strong> 。&lt;/p>
&lt;p>那麼，我們需要傳入的參數值有：&lt;br>
&lt;strong>combo&lt;/strong> (當前未完成的組合), &lt;strong>res&lt;/strong> (記錄結果的所有已完成的組合),&lt;br>
&lt;strong>n&lt;/strong> (1~n的數字), k(&lt;strong>連同當前這輪，還有幾個數字要被納入組合&lt;/strong> ),&lt;br>
&lt;strong>i&lt;/strong> (當前走到的數字)&lt;/p>
&lt;p>那麼，我們可以使用遞迴(命名為findCombos)來處理這題，&lt;br>
當&lt;strong>k等於0&lt;/strong> 時，表示&lt;strong>已經完成這個組合，將其加入res中&lt;/strong> ；&lt;br>
否則當&lt;strong>i ≤ n&lt;/strong> 時，表示還有** 可以選擇的數字**(** 且組合還沒完成**)，&lt;br>
此時可以分成 &lt;strong>a.&lt;/strong> ** 將i加入combo 或 b. 不加入combo** 中。&lt;br>
&lt;strong>a. 將i加入combo中的話&lt;/strong> -&amp;gt; ** 代入findCombos的遞迴中k要減1，i要加1。&lt;br>
且這輪下去遞迴完以後，記得將狀態復原(把combo的最後一個數字拿掉)&lt;br>
b. 不將i加入combo的話** -&amp;gt; 代入findCombos的遞迴僅需i要加1即可。&lt;br>
(因為只有當前選擇的數字增加)&lt;/p>
&lt;p>除此以外，我們可以額外考慮一件事情：&lt;br>
由於&lt;strong>剩下的可選數字應該大於我們還需要選擇的數字&lt;/strong> ，&lt;br>
所以 &lt;strong>i≤n&lt;/strong> 的條件應該可以進一步縮限成 ** i+k-1 ≤ n**。&lt;/p>
&lt;p>依此，寫成如下的程式碼。&lt;/p>
&lt;p>Java的部分，可以使用ArrayList/LinkedList皆可，&lt;br>
並且保險起見，可以先行檢查n和k。&lt;br>
(畢竟測資也有可能弄個不合法的負數或零)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/49e8608b732ca7e4e5c5a8cb97bbf041.js">&lt;/script>
&lt;p>如之前的文章，Python請不要忘記append到combo上的必須是複製的list。&lt;br>
此外也可以使用itertools的combination來直接得到答案，&lt;br>
但&lt;strong>請不要&lt;/strong> 在面試的時候這樣用XD&lt;br>
(因為這只證明了你知道工具，而不是你懂回溯法)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9b53e51c03b38e361cd20bf7f3523a40.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(C(n, k))/O(k*C(n,k))。&lt;br>
由於k的値會影響階乘連接的個數，所以不好化簡。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 62 Tree (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-62-tree-10/</link><pubDate>Wed, 16 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-62-tree-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 62 Tree (10)" />&lt;p>&lt;strong>0102. Binary Tree Level Order Traversal (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, return the &lt;em>level order&lt;/em> traversal of its nodes’ values. (ie, from left to right, level by level).&lt;/p>
&lt;p>For example:&lt;br>
Given binary tree &lt;code>[3,9,20,null,null,15,7]&lt;/code>,&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 20
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 15 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>return its level order traversal as:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [9,20],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [15,7]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，回傳其節點値的層序遍歷結果。&lt;/p>
&lt;p>我們在&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"
>先前的文章&lt;/a>中，&lt;br>
已經提到過層序走訪(level-order traversal)的概念了，&lt;br>
按照題目範例，這邊要將level分層開來。&lt;/p>
&lt;p>對於&lt;strong>遞迴&lt;/strong> 解來說，如果使用一般的DFS的話，&lt;br>
我們將不知道哪一個節點位在哪一個level上，&lt;br>
故我們將必須&lt;strong>加入變數level&lt;/strong> ，&lt;br>
讓level的值來幫助我們辨別要加到List的哪個level區塊中。&lt;/p>
&lt;p>所以對於遞迴解而言，在&lt;strong>主函式&lt;/strong> 中：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>檢查根節點&lt;/strong>&lt;/li>
&lt;li>將root的值加入&lt;strong>第0層的list&lt;/strong> 中，再將該list加到答案&lt;strong>res&lt;/strong> 中&lt;/li>
&lt;li>呼叫幫助用的函式，&lt;strong>將level遞増代入&lt;/strong> (表下一層)&lt;/li>
&lt;/ol>
&lt;p>在&lt;strong>幫助用函式&lt;/strong> 中：&lt;/p>
&lt;ol>
&lt;li>先檢查代入進來的節點，&lt;br>
若&lt;strong>遇到NIL則表示到此為止&lt;/strong> ，進行回傳即可。&lt;/li>
&lt;li>檢查目前&lt;strong>res的size&lt;/strong> 和&lt;strong>level&lt;/strong> 的關係，&lt;br>
若相等則表示要開一個新的list(因為&lt;strong>level從0起算&lt;/strong> )；&lt;br>
否則，找到對應level的list，將該節點的值加入。&lt;/li>
&lt;li>分別檢查左節點和右節點&lt;strong>進行遞迴&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>觀察這樣子的遍歷方式，讀者應該可以發現一點：&lt;br>
&lt;strong>幫助用的函式本質上就是在做pre-order traversal。&lt;/strong> 之所以會達成我們想要的效果，是因為我們額外記錄了level這個資訊。&lt;/p>
&lt;p>如果使用&lt;strong>迭代法&lt;/strong> 來解呢？&lt;br>
我們可以建立一個&lt;strong>Queue&lt;/strong> ，在每一層&lt;strong>先行取得Queue的大小(長度)&lt;/strong> ，&lt;br>
每次迴圈只要剛好執行這個次數，&lt;br>
就可以不斷&lt;strong>利用相同的Queue來堆出不同的層數&lt;/strong> ，&lt;br>
再分頭&lt;strong>將對應的左節點和右節點推入Queue中&lt;/strong> 。&lt;br>
(記得要先檢查，非NIL才需要推入)&lt;br>
&lt;strong>最終所有節點都遍歷過一遍時，&lt;br>
剛好Queue裡面也不會留存任何節點。&lt;/strong>&lt;/p>
&lt;p>依照上述說明，請參考對應的程式碼。&lt;/p>
&lt;p>Java的部分，記得用來檢查的&lt;strong>isEmpty()&lt;/strong> ，以及可以用&lt;strong>LinkedList&lt;/strong> 來實作&lt;strong>Queue&lt;/strong> 的部分。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/bef29b911d5d5fc9adf83bcc6baf5bf5.js">&lt;/script>
&lt;p>Python用&lt;strong>deque&lt;/strong> (記得我們提到過的，&lt;strong>list在移除左端的部分效率較差&lt;/strong> )&lt;br>
另外，若幫助函式沒有要再被其他函式使用，&lt;br>
是可以考慮如底下34行以後這樣子寫成子函式的方式再呼叫的，&lt;br>
可以省去要加一堆self的狀況。&lt;br>
(但要記得：Python函式要&lt;strong>先宣告才能呼叫&lt;/strong> )&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/16ecc6189b7f5f63b5733d2f5f9fb600.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，因為要遍歷全部節點並記錄)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 61 Dynamic Programming (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-61-dynamic-programming-9/</link><pubDate>Sun, 13 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-61-dynamic-programming-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 61 Dynamic Programming (9)" />&lt;p>&lt;strong>1140. Stone Game II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="寫在前面">寫在前面
&lt;/h2>&lt;p>大家連假過的好嗎XD？筆者到新加坡玩了一趟，不好意思好幾天沒更新啦~&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Alex and Lee continue their games with piles of stones. There are a number of piles &lt;strong>arranged in a row&lt;/strong> , and each pile has a positive integer number of stones &lt;code>piles[i]&lt;/code>. The objective of the game is to end with the most stones.&lt;/p>
&lt;p>Alex and Lee take turns, with Alex starting first. Initially, &lt;code>M = 1&lt;/code>.&lt;/p>
&lt;p>On each player’s turn, that player can take &lt;strong>all the stones&lt;/strong> in the ** first** &lt;code>X&lt;/code> remaining piles, where &lt;code>1 &amp;lt;= X &amp;lt;= 2M&lt;/code>. Then, we set &lt;code>M = max(M, X)&lt;/code>.&lt;/p>
&lt;p>The game continues until all the stones have been taken.&lt;/p>
&lt;p>Assuming Alex and Lee play optimally, return the maximum number of stones Alex can get.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: piles = [2,7,9,4,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: If Alex takes one pile at the beginning, Lee takes two piles, then Alex takes 2 piles again. Alex can get 2 + 4 + 4 = 10 piles in total. If Alex takes two piles at the beginning, then Lee can take all three piles left. In this case, Alex get 2 + 7 = 9 piles in total. So we return 10 since it&amp;#39;s larger.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="constraints">Constraints
&lt;/h3>&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= piles.length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= piles[i] &amp;lt;= 10 ^ 4&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>聽說之前有人一直嗆說怎麼都沒人能夠將1140這題講清楚？&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-61-dynamic-programming-9/image-001.png"
width="225"
height="225"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-61-dynamic-programming-9/image-001_hu062e6af5dc2b05633b3d842f0acd9ada_15975_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-61-dynamic-programming-9/image-001_hu062e6af5dc2b05633b3d842f0acd9ada_15975_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;p>這題其實題目不難理解：&lt;br>
Alex和Lee兩個人玩搶石頭的遊戲，石頭被分成數堆，&lt;br>
使用piles[i]來記錄，遊戲目的是在結尾時拿到最多的石頭。&lt;br>
Alex和Lee輪流拿石頭(&lt;strong>Alex先&lt;/strong> )，&lt;strong>最開始的時候M設定為1&lt;/strong> 。&lt;br>
每次玩家要決定拿剩下的&lt;strong>前X堆的所有石頭&lt;/strong> (必須按順序&lt;strong>不可以跳過&lt;/strong> )，&lt;br>
X的範圍是1 ≤ X ≤ 2M；接下來就要依照X來更新M：&lt;strong>M = max(M, X)&lt;/strong>&lt;/p>
&lt;p>直到所有石頭都被拿光，遊戲就結束了。&lt;br>
假定Alex和Lee都以最佳化的狀況來玩這個遊戲(play optimally)，&lt;br>
回傳Alex在遊戲結束時最多能拿到的石頭。&lt;/p>
&lt;p>在所謂&amp;quot;play optimally&amp;quot;的遊戲中，&lt;br>
我們會假設參與的玩家都清楚&lt;strong>知道所有人的策略&lt;/strong> ，&lt;br>
並且&lt;strong>選擇對自己利益最大的選擇&lt;/strong> 。&lt;br>
依照這樣子的概念，我們其實可以感覺到前後會有所關聯，&lt;br>
因為對於雙方來說都是想要&lt;strong>最大化自己拿到的石頭&lt;/strong> ；&lt;br>
又，&lt;strong>自己拿到最多，就意味著對方拿到最少&lt;/strong> ，&lt;br>
所以這點同時還隱含了中間的可能會有一些判斷，&lt;br>
比如像是X這類型的變數對於同樣從第i堆開始來說，&lt;br>
要走哪個方向又會都有各自的分支，需要好好考慮才行。&lt;/p>
&lt;p>我們先假定有一個函數dp，&lt;br>
這個函數可以計算當現在要從pile[i]開始拿的時候，&lt;br>
(也就是0~i-1堆都被拿光了)&lt;br>
輪到的玩家在這次及這輪以後所能拿到的石頭數的最大值。&lt;br>
顯然這還會有另一個變數M，&lt;br>
因為M能夠決定這輪最大可以拿到的堆數(2M)。&lt;br>
因此我們將這個函數表示成dp(i, M)。&lt;/p>
&lt;p>&lt;strong>先討論一個最簡單的狀況：&lt;/strong>&lt;br>
當&lt;strong>i+2M ≥ n-1&lt;/strong> 的時候，(假設總石頭的堆數是n)&lt;br>
表示這個玩家可以直接選擇&lt;strong>將剩下的石堆全取走&lt;/strong> ，&lt;br>
就會是他所能拿到的石頭量的最大值。&lt;br>
&lt;strong>(因為遊戲就結束了，另一個玩家什麼都拿不到)&lt;/strong>&lt;br>
所以這個就會是這個dp的&lt;strong>確定值&lt;/strong> 的部分了。&lt;/p>
&lt;p>接下來我們討論另一個狀況：(假設是A跟B玩家輪流拿石頭)&lt;br>
假設&lt;strong>A玩家取了x堆&lt;/strong> ，接下來會發生什麼事情呢？&lt;br>
輪到下一個玩家B了，對吧？&lt;br>
那麼玩家要從&lt;strong>i+x堆&lt;/strong> 的位置開始拿取，&lt;br>
而此時的M按照遊戲規則是&lt;strong>max(M,x)&lt;/strong> 。&lt;br>
&lt;strong>由於B同樣也是play optimally&lt;/strong> ，&lt;br>
所以B也想&lt;strong>最大限度的在這整場遊戲中獲得較多的石頭&lt;/strong> ，&lt;br>
故對B而言在i+x堆開始拿取的數字按照定義就是&lt;strong>dp(i+x, max(M,x))&lt;/strong> 。&lt;/p>
&lt;p>那麼關鍵來了：&lt;br>
對於&lt;strong>dp(i,M)&lt;/strong> 而言，固定不變的會是從&lt;strong>pile[i]到最後的石堆的石頭總量&lt;/strong> ，&lt;br>
我們暫時先命名為Si, &lt;strong>Si = pile[i]~ pile[N-1]的和&lt;/strong> 。&lt;br>
所以會變動的就只有B拿的部分而已。&lt;br>
所以我們可以得到&lt;strong>dp(i, M) = Si - dp(i+x, max(M, x))&lt;/strong> 。&lt;/p>
&lt;p>又實際上我們一開始也不知道x應該取多少會最好，&lt;br>
&lt;strong>所以x的範圍一樣是1~2M&lt;/strong> ，也就是我們要在x是這個範圍的所有狀況下，&lt;br>
&lt;strong>找出dp(i+x, max(M, x))的最小值，從而得到dp(i, M)&lt;/strong> 。&lt;br>
(因為&lt;strong>想要A拿的最多，就是要B拿的最少&lt;/strong> ，故要取後者的最小值)&lt;/p>
&lt;p>在實務上，我們可以拿前面的piles來計算Si，只要一路&lt;strong>從尾到頭&lt;/strong> ，&lt;br>
將piles的値往回加即可(因為Si = piles[i]&lt;del>piles[N-1]的和)。&lt;br>
我們需要一個二維陣列dp[][]，&lt;br>
&lt;strong>第一個維度表示i&lt;/strong> (範圍是**0&lt;/del>n-1** )&lt;br>
&lt;strong>第二個維度表示M&lt;/strong> (範圍是&lt;strong>1~(n-1)/2 + 1&lt;/strong> ，但為了方便起見，&lt;br>
我們陣列只使用1開始的部分以避免位移，&lt;br>
所以再加一以後，我們第二維的長度會是**(n+1)/2 + 1** )&lt;/p>
&lt;p>我們整理一下實際的演算流程。&lt;br>
&lt;strong>主函式中:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>從尾到頭&lt;/strong> 將&lt;strong>piles[i+1]&lt;/strong> 加到&lt;strong>piles[i]&lt;/strong> 上，&lt;br>
讓&lt;strong>piles[i]現在代表從第i堆開始的所有石頭數&lt;/strong> 。&lt;/li>
&lt;li>新增一個二維陣列&lt;strong>dp[][]&lt;/strong> 以表示在**(i, M)** 條件下所能取得石頭的最大値。&lt;/li>
&lt;li>呼叫helper函式來&lt;strong>遞迴&lt;/strong> 處理。&lt;br>
&lt;strong>在helper函式中:&lt;/strong>&lt;/li>
&lt;li>如果i已經走超過了則&lt;strong>回傳0&lt;/strong> (表遊戲結束)&lt;/li>
&lt;li>如果2*M &amp;gt;= len(piles) - i則回傳&lt;strong>piles[i]&lt;/strong> (&lt;strong>一口氣取完剩下的石頭&lt;/strong> )&lt;/li>
&lt;li>當dp[i][M]尚未被計算出値的時候，&lt;br>
&lt;strong>遞迴搜尋dp[i+x][max(M,x)]的最小值&lt;/strong> ，(x範圍是1~2*M)&lt;br>
(已知値的話則直接代入)&lt;/li>
&lt;li>&lt;strong>dp[i][M]等於piles[i]減去前述的最小值&lt;/strong>&lt;/li>
&lt;li>&lt;strong>回傳dp[i][M]&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>依此，寫成程式碼：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/70f5ac33c747358d2012c394e6e8a29d.js">&lt;/script>
&lt;p>Python的部分，可將遞迴的部分搭配&lt;br>
&lt;strong>for x in range(1, 2 * M + 1)&lt;/strong> 看起來會更簡潔。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/50316eca545c6342f3ab2ca3e194003c.js">&lt;/script>
&lt;p>Python的部份根據大神&lt;a class="link" href="https://leetcode.com/problems/stone-game-ii/discuss/345230/Python-DP-Solution" target="_blank" rel="noopener"
>lee215的解答&lt;/a>，還可以做一些簡化：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c6a0f6">def&lt;/span> &lt;span style="color:#8aadf4">stoneGameII&lt;/span>(&lt;span style="color:#91d7e3">self&lt;/span>, A: List[&lt;span style="color:#f5a97f">int&lt;/span>]) &lt;span style="color:#91d7e3;font-weight:bold">-&amp;gt;&lt;/span> &lt;span style="color:#f5a97f">int&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> N &lt;span style="color:#91d7e3;font-weight:bold">=&lt;/span> len(A)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c6a0f6">for&lt;/span> i &lt;span style="color:#91d7e3;font-weight:bold">in&lt;/span> &lt;span style="color:#91d7e3">range&lt;/span>(N &lt;span style="color:#91d7e3;font-weight:bold">-&lt;/span> &lt;span style="color:#f5a97f">2&lt;/span>, &lt;span style="color:#91d7e3;font-weight:bold">-&lt;/span>&lt;span style="color:#f5a97f">1&lt;/span>, &lt;span style="color:#91d7e3;font-weight:bold">-&lt;/span>&lt;span style="color:#f5a97f">1&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> A[i] &lt;span style="color:#91d7e3;font-weight:bold">+=&lt;/span> A[i &lt;span style="color:#91d7e3;font-weight:bold">+&lt;/span> &lt;span style="color:#f5a97f">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> from functools import lru_cache
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ed8796">@&lt;/span>lru_cache(None)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c6a0f6">def&lt;/span> &lt;span style="color:#8aadf4">dp&lt;/span>(i, m):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c6a0f6">if&lt;/span> i &lt;span style="color:#91d7e3;font-weight:bold">+&lt;/span> &lt;span style="color:#f5a97f">2&lt;/span> &lt;span style="color:#91d7e3;font-weight:bold">*&lt;/span> m &lt;span style="color:#91d7e3;font-weight:bold">&amp;gt;=&lt;/span> N: &lt;span style="color:#c6a0f6">return&lt;/span> A[i]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c6a0f6">return&lt;/span> A[i] &lt;span style="color:#91d7e3;font-weight:bold">-&lt;/span> &lt;span style="color:#91d7e3">min&lt;/span>(dp(i &lt;span style="color:#91d7e3;font-weight:bold">+&lt;/span> x, &lt;span style="color:#91d7e3">max&lt;/span>(m, x)) &lt;span style="color:#c6a0f6">for&lt;/span> x &lt;span style="color:#91d7e3;font-weight:bold">in&lt;/span> &lt;span style="color:#91d7e3">range&lt;/span>(&lt;span style="color:#f5a97f">1&lt;/span>, &lt;span style="color:#f5a97f">2&lt;/span> &lt;span style="color:#91d7e3;font-weight:bold">*&lt;/span> m &lt;span style="color:#91d7e3;font-weight:bold">+&lt;/span> &lt;span style="color:#f5a97f">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c6a0f6">return&lt;/span> dp(&lt;span style="color:#f5a97f">0&lt;/span>, &lt;span style="color:#f5a97f">1&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>lru_cache&lt;/strong> 可以將函式已經計算過的結果直接快取放置在記憶體中，&lt;br>
當再次需要計算値的時候，&lt;strong>不經過計算，直接將値回傳&lt;/strong> 。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N³)/O(N²)，因為記錄所有解要對應到二維陣列，&lt;br>
而對於每一個陣列解都需要往下搜尋O(N)的長度來比較得出最小值。)&lt;/p>
&lt;p>「為什麼要記錄一個dp的陣列？&lt;strong>不能直接靠遞迴記錄嗎&lt;/strong> ？」&lt;br>
(遞迴記錄&lt;strong>同樣要使用記憶體空間&lt;/strong> ，且因為中間拆解時，&lt;br>
&lt;strong>可能會有重複的(i, M)出現，不先記錄的話會造成有重複計算的狀況。&lt;/strong> )&lt;/p>
&lt;p>「這題是否可以用迭代法解？」&lt;br>
(可以，請參閱&lt;a class="link" href="https://leetcode.com/problems/stone-game-ii/discuss/355710/Java-simple-DP-solution-with-explanation" target="_blank" rel="noopener"
>yzstone的解法&lt;/a>。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 60 Backtracking (3) / DFS (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-60-backtracking-3-dfs-5/</link><pubDate>Mon, 07 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-60-backtracking-3-dfs-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 60 Backtracking (3) / DFS (5)" />&lt;p>&lt;strong>0078. Subsets (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a set of &lt;strong>distinct&lt;/strong> integers, &lt;em>nums&lt;/em>, return all possible subsets (the power set).&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> The solution set must not contain duplicate subsets.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: nums = [1,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [2],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,2,3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [2,3],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1,2],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一組內含相異的整數的集合nums，試回傳其power set。&lt;br>
(所有可能的子集合，包含空集合)&lt;/p>
&lt;p>我們先考慮一下所謂的子集合。&lt;br>
所謂的子集合就是在指說，在nums所有的元素(element)中，&lt;br>
有哪些要被用，哪些不要被用的所有組合。&lt;br>
所以對於每個數都有加進去/不加進去的兩種可能，&lt;br>
如果nums有N個元素，所有的組合的可能是就會是2^N。&lt;/p>
&lt;p>我們可以透過上述的思路來建構遞迴的函式。&lt;br>
首先，我們先產生一個subset，&lt;br>
用來&lt;strong>存放走到當前的狀況&lt;/strong> ，&lt;br>
&lt;strong>而一個確定可以放進結果res的subset，&lt;br>
必須是將整個nums走完且決定誰要進，誰不要進才行。&lt;/strong>&lt;br>
要放進subset和不放都是可行的選擇，&lt;br>
那麼我們就必須要&lt;strong>分岔成兩條路&lt;/strong> ：&lt;/p>
&lt;ol>
&lt;li>將當前遇到的數字置之不理，&lt;strong>直接朝向下一個index走&lt;/strong>&lt;/li>
&lt;li>&lt;strong>先將當前遇到的數字加進subset中&lt;/strong> ，再朝下一個index走&lt;br>
留意當&lt;strong>回到上一層&lt;/strong> 的時候，這個index遇到的數字同樣&lt;strong>應該要被取消掉&lt;/strong> ，&lt;br>
所以我們應該要&lt;strong>從subset中拔掉最後一個數字&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>那麼&lt;strong>遞迴的尾端&lt;/strong> ，自然就是當index&lt;strong>走超過範圍&lt;/strong> 的時候，&lt;br>
此時我們應該&lt;strong>將這個subset作為其中一個結果放入到res中，&lt;/strong>&lt;br>
&lt;strong>並回到上一層。&lt;/strong>&lt;/p>
&lt;p>依此，我們可以寫成如下的程式碼。&lt;br>
在Java的部分，List使用LinkedList或ArrayList皆可，&lt;br>
ArrayList適用於需要取得某個點的値，&lt;br>
而LinkedList在儲存時會稍微快一點，&lt;br>
請留意我們在新增組合時是使用&lt;strong>new ArrayList&amp;lt;&amp;gt;(subset)&lt;/strong> ，&lt;br>
用以加入subset的複本來放入res中。&lt;br>
&lt;strong>如果單純放subset的話，由於大家都指向相同的位置，&lt;br>
後面修改subset的時候會導致res內的內容也同部被改到，&lt;br>
請務必留意XD&lt;/strong>&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/471ea22f9965dac78c83ae46a3bd0496.js">&lt;/script>
&lt;p>這邊也提供了參考的其它解，包含了迭代解和另一種遞迴解，&lt;br>
概念都是**拿現在的所有組合和新的數字，決定要加或不要加，&lt;br>
用以衍生出兩倍的組合。**這種方法其實概念上類似我們之前提到的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-11-bitwise-operation-1-3117c4ce925d" target="_blank" rel="noopener"
>Gray Code&lt;/a>的解法，&lt;br>
用原先的部分來組新的東西，有興趣可再參考。&lt;/p>
&lt;p>Python的部分一樣需注意subset要使用copy來複製一份使用。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/12f4afa1f169926a36e33f031860c7e1.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(2^N)/O(2^N)，因每種組合皆須經過一次，且都要存入結果。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 59 Backtracking (2) / DFS (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-59-backtracking-2-dfs-4/</link><pubDate>Fri, 04 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-59-backtracking-2-dfs-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 59 Backtracking (2) / DFS (4)" />&lt;p>&lt;strong>0079. Word Search (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a 2D board and a word, find if the word exists in the grid.&lt;/p>
&lt;p>The word can be constructed from letters of a sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>board =
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [&amp;#39;A&amp;#39;,&amp;#39;B&amp;#39;,&amp;#39;C&amp;#39;,&amp;#39;E&amp;#39;],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [&amp;#39;S&amp;#39;,&amp;#39;F&amp;#39;,&amp;#39;C&amp;#39;,&amp;#39;S&amp;#39;],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [&amp;#39;A&amp;#39;,&amp;#39;D&amp;#39;,&amp;#39;E&amp;#39;,&amp;#39;E&amp;#39;]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given word = &amp;#34;ABCCED&amp;#34;, return true.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Given word = &amp;#34;SEE&amp;#34;, return true.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Given word = &amp;#34;ABCB&amp;#34;, return false.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個2維棋盤和一個字(word)，檢查這個字是否存在這個棋盤裡。&lt;br>
構成字的方式是從棋盤的某一格開始，連續選取相鄰的格子。&lt;br>
同時，相同的格子不能使用兩次。&lt;/p>
&lt;p>前面提到過Backtracking(回溯法)，&lt;br>
這題同樣也是典型的DFS+Backtracking方法可以處理的對象。&lt;/p>
&lt;p>首先，要構成一個字，就要從&lt;strong>棋盤上選擇一個位置開始往下&lt;/strong> 。&lt;br>
每次選一個相鄰的格子，拿來跟word比對，&lt;br>
都必須要和word對應的位置上的字元(char)相同才行，&lt;br>
所以這表示我們還要&lt;strong>記錄現在比對到哪個index&lt;/strong> 了。&lt;br>
同時，由於用過的格子不能重複使用，每次在進入dfs的時候，&lt;br>
我們必須要&lt;strong>記錄是否有造訪(visit)過這個格子&lt;/strong> ，&lt;br>
才往更深處呼叫；同時，在該層的&lt;strong>四個方向都判斷完以後&lt;/strong> ，&lt;br>
&lt;strong>回到上一層之前，必須將造訪的紀錄還原回去&lt;/strong> 。&lt;br>
(因為我們只有在這次走這條路的時候有造訪，&lt;br>
回到上一層的時候這個格子應該處於沒有造訪過的狀態)&lt;/p>
&lt;p>所以最開始我們要做的事情是，&lt;br>
&lt;strong>使用迴圈分別將每個cell作為起始點，開始進行搜尋。&lt;br>
(搜尋的遞迴函式如果其中一次是True的話就可以直接回傳True)&lt;/strong>&lt;/p>
&lt;p>每次搜尋的時候，傳入的有：&lt;br>
&lt;strong>board(棋盤), r, c(當前的cell位置), &lt;br>
index(比對到word的哪一個char), word&lt;/strong>&lt;/p>
&lt;p>每一次我們要做的步驟：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>檢查board[r][c]和word的index處的值是否不同&lt;/strong> ，&lt;br>
&lt;strong>不同則回傳False&lt;/strong> 表示這條路行不通。&lt;/li>
&lt;li>檢查&lt;strong>index&lt;/strong> 是否已經走到最後了(&lt;strong>length of word - 1&lt;/strong> )，&lt;br>
是的話代表&lt;strong>這條路到這邊剛好就是答案，回傳True&lt;/strong> 。&lt;/li>
&lt;li>將&lt;strong>index遞增&lt;/strong> (接下來要給下面遞迴使用)，並&lt;strong>將board[r][c]標明已造訪&lt;/strong> 。&lt;/li>
&lt;li>分別以往&lt;strong>上下左右&lt;/strong> 方向的&lt;strong>新的(r, c)值來代入函式進行遞迴搜尋&lt;/strong> ，&lt;br>
&lt;strong>如果結果是True的話，直接回傳True&lt;/strong> 。(也就是下面的部份都不用做了XD)&lt;br>
(這邊記得要&lt;strong>檢查上下左右移動一格以後是否超出board範圍&lt;/strong> )&lt;/li>
&lt;li>前面四個都是False的狀況，代表這條路行不通了，&lt;br>
我們要回到上一步，這時候要&lt;strong>先將board[r][c]標明未造訪&lt;/strong> ，&lt;br>
才&lt;strong>回傳False&lt;/strong> 。&lt;/li>
&lt;/ol>
&lt;p>如果跑完整個棋盤，都沒有能夠成立的路徑的話，&lt;br>
就應該&lt;strong>回傳False&lt;/strong> 作為答案。(因為我們沒有找到可行的路徑)&lt;/p>
&lt;p>在實作時為了方便起見，我們可以宣告class的變數來放一些常用的東西，&lt;br>
這邊用了wlen(word的長度), row, col(board的列/行數)。&lt;br>
需要注意的是，在實作造訪與否的紀錄時，&lt;br>
我們可以選擇使用像是visited[][]的二維陣列來寫，&lt;br>
但也可以採用別的方法，比如將裡面的值暫時設為&amp;quot;0&amp;quot;，&lt;br>
後面再還原，或者像Java這邊寫的將其&lt;strong>和128進行XOR&lt;/strong> 。&lt;/p>
&lt;p>為什麼和128進行XOR呢？&lt;br>
因為&lt;a class="link" href="https://zh.wikipedia.org/zh-tw/ASCII" target="_blank" rel="noopener"
>ASCII&lt;/a>中的所有字元值均不超過128，&lt;br>
也就是說，它們在&lt;strong>二進位上的第8位數(由右數到左)均為0&lt;/strong> 。&lt;br>
XOR後，第8位數會變成1，所以再度遞迴下去比對時，&lt;br>
就不可能等於任何字元，從而達到標示造訪過的目的。&lt;/p>
&lt;p>還原回來的時候，因為：&lt;br>
a XOR 128 XOR 128 ＝ a XOR 0 = a&lt;br>
(&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-15-bitwise-operation-2-b3084a69698f" target="_blank" rel="noopener"
>&lt;strong>先前的文章&lt;/strong> &lt;/a>有提到過的Bitwise Operation)&lt;/p>
&lt;p>所以&lt;strong>再重複用128進行一次XOR即可還原原先的值&lt;/strong> 了！&lt;/p>
&lt;p>寫成程式碼如下：&lt;br>
(留意Java可以&lt;strong>直接對char當作是數字來操作&lt;/strong> )&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/ecf56cb50c83a8b2f953cb8ec92dce67.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/168bc64792811dd2546e07934435de3e.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(如果row = m, col = n，word長度=l的話，從每個點出發一次，&lt;br>
並且每次都有4個方向的選擇(但只有三個方向能繼續延伸)，&lt;br>
時間複雜度會是O(m * n * 3^L)。&lt;br>
空間複雜度的部分，如果考慮call stack的話，最大會是O(L)，&lt;br>
不考慮的話，由於沒有使用visited[][]來處理，則會是O(1)。&lt;br>
如果用visited來存放的話則是O(m*n))&lt;/p>
&lt;p>「在Python中是否可以使用類似Java對char的解法來處理呢？」&lt;br>
(可以，請使用ord()將單個字元進行轉換成數字再進行xor，&lt;br>
不能直接用str型態的値來處理。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
Raiy Kuo: 細算的話選擇方向這部份的時間複雜度是3^L，&lt;br>
詳情請見response中的討論。&lt;/strong>&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 58 Two Pointer (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-58-two-pointer-2/</link><pubDate>Tue, 01 Oct 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-58-two-pointer-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 58 Two Pointer (2)" />&lt;p>&lt;strong>0075. Sort Colors (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array with &lt;em>n&lt;/em> objects colored red, white or blue, sort them &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
>&lt;strong>in-place&lt;/strong> &lt;/a>so that objects of the same color are adjacent, with the colors in the order red, white and blue.&lt;/p>
&lt;p>Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> You are not supposed to use the library’s sort function for this problem.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,0,2,1,1,0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [0,0,1,1,2,2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>A rather straight forward solution is a two-pass algorithm using counting sort.&lt;br>
First, iterate the array counting number of 0’s, 1’s, and 2’s, then overwrite the array with the total number of 0’s, then 1’s and followed by 2&amp;rsquo;s.&lt;/li>
&lt;li>Could you come up with a one-pass algorithm using only constant space?&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個陣列當中有n個物件，被著色成紅、白、藍，&lt;br>
請將其以in-place的方式將同顏色排序至相鄰，並順序亦為紅白藍。&lt;br>
這裡給定的陣列顏色紅/白/藍分別以0/1/2代表。&lt;/p>
&lt;p>如果有印象的話，大家可能還記得之前有一題&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-25-array-3-bca3bca74ca2?source=friends_link&amp;amp;sk=2b26f2e316bbfd7bc96ff372259e652a" target="_blank" rel="noopener"
>Move Zeroes&lt;/a>，&lt;br>
差別在於這題是0, 1, 2，我們依舊可以用類似的概念來解題。&lt;/p>
&lt;p>使用3個變數來分別記錄0/1/2的個數，&lt;br>
等到計完了，再依序覆寫到nums裡面，就可以得到答案，&lt;br>
這麼做會需要&lt;strong>掃過陣列兩次，第一次用來計數，第二次用來填入新的値。&lt;/strong>&lt;/p>
&lt;p>那麼，題目也問了：&lt;br>
有沒有辦法給出一個&lt;strong>one-pass&lt;/strong> 的演算法來解此題呢？&lt;br>
(one-pass algorithm意思是指說只掃過整個資料一次，詳見&lt;a class="link" href="https://en.wikipedia.org/wiki/One-pass_algorithm" target="_blank" rel="noopener"
>wiki&lt;/a>)&lt;/p>
&lt;p>我們可以仿照先前的&lt;strong>Two Pointer&lt;/strong> 的概念來思考。&lt;br>
首先，1在這個陣列當中是我們較不在意的部分，&lt;br>
因為它一定是排在整個陣列的中間，&lt;br>
然後左邊區塊最後會是0，右邊區塊最後會是2。&lt;/p>
&lt;p>假設我們要排序，所要做的就是&lt;strong>將0的部分都往左邊擺，&lt;br>
將2的部分都往右邊擺&lt;/strong>；最開始的時候，因為還沒排過，&lt;br>
我們可以將下一個要擺放的位置命名為i0和i2，&lt;br>
並假定應該要擺在0和n-1的位置。(陣列的最左邊和最右邊)&lt;br>
接下來，依序掃描整個陣列(假設迭代的index為i)，會有以下三個情況。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>碰到1:&lt;br>
因為將0和2都擺完以後1自然在中間，所以完全不用管它XD&lt;/p>
&lt;/li>
&lt;li>
&lt;p>碰到0:&lt;br>
我們應該&lt;strong>將其擺放在i0的位置&lt;/strong> ，&lt;br>
但原先i0所在的値不能平白消失，所以將其和i位置的値相交換。&lt;br>
換完之後，&lt;strong>i0&lt;/strong> 因為已經填入0了，&lt;br>
故&lt;strong>下個要填入0的位置必須更新&lt;/strong> ，所以&lt;strong>將i0遞增&lt;/strong> 。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>碰到2:&lt;br>
同理，&lt;strong>將其擺在i2的位置，和i位置的値相交換，再遞減i2&lt;/strong> ；&lt;br>
需要注意的是由於&lt;strong>i的位置換到我們不知道值的部分&lt;/strong> ，&lt;br>
&lt;strong>(前面碰到0的時候換的應該都是1，所以沒有影響)&lt;/strong>&lt;br>
所以&lt;strong>將i遞減，抵銷掉i在整個迴圈中每次加1的部分&lt;/strong> ，&lt;br>
以便迴圈的下一輪能檢查相同的位置。(&lt;strong>檢查換過來的値&lt;/strong> )&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>這整個迴圈的結束時間點應該在&lt;strong>i和i2交錯的時候&lt;/strong> ，&lt;br>
因為這代表後面都是2，既然後面已經相當於排完，&lt;br>
就可以結束整個迴圈了！&lt;/p>
&lt;p>寫成程式碼如下，&lt;br>
幾個需要簡單注意的地方是，&lt;br>
當使用&lt;strong>第一種方法&lt;/strong> 的時候，&lt;br>
其實可以直接開一個&lt;strong>長度為3的陣列&lt;/strong> 來儲存數字出現次數；&lt;br>
其次，使用&lt;strong>第二種方法&lt;/strong> 時，Python當&lt;strong>需要判定條件會改變的狀&lt;/strong> 況時，&lt;br>
&lt;strong>請使用while迴圈&lt;/strong> ，因為for in range的寫法沒辦法動態地去改變條件。&lt;br>
(另外別忘記Python沒有++或 — ，請用+=和-=)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e3be7e43c19f078a715e2796a389025d.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e498d8ad24ef8d39e560e096cdf4932a.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，不論哪個解法，最多就是掃描過2次的nums的長度，&lt;br>
且我們基本上只會用到三個記錄各自數量的變數或三個索引值)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-36-merge-sort-1-21dde785b0df?source=friends_link&amp;amp;sk=df2e91f82ce0fe4fb91c6866e87549dc" target="_blank" rel="noopener"
>&lt;strong>0148. Sort List (Medium)&lt;/strong> &lt;/a>2.&lt;a class="link" href="https://leetcode.com/problems/wiggle-sort-ii/" target="_blank" rel="noopener"
>&lt;strong>0324. Wiggle Sort II (Medium)&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 57 Binary Search (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-57-binary-search-4/</link><pubDate>Sun, 29 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-57-binary-search-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 57 Binary Search (4)" />&lt;p>&lt;strong>0074. Search a 2D Matrix (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write an efficient algorithm that searches for a value in an &lt;em>m&lt;/em> x &lt;em>n&lt;/em> matrix. This matrix has the following properties:&lt;/p>
&lt;ul>
&lt;li>Integers in each row are sorted from left to right.&lt;/li>
&lt;li>The first integer of each row is greater than the last integer of the previous row.&lt;/li>
&lt;/ul>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>matrix = [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1, 3, 5, 7],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [10, 11, 16, 20],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [23, 30, 34, 50]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>target = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>matrix = [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1, 3, 5, 7],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [10, 11, 16, 20],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [23, 30, 34, 50]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>target = 13
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個m x n的矩陣，此矩陣每列(row)都是從左到右升冪排序；&lt;br>
同時此矩陣每列的第一個值都比前一個列的最後一個值還要大。&lt;br>
試找出一個有效率的演算法，&lt;br>
來處理在這個矩陣搜尋一個值是否在這裡面。&lt;/p>
&lt;p>有沒有覺得很熟悉？&lt;br>
其實這題的延伸題目就是上一題，作為同樣Medium難度的題目，&lt;br>
這題就要來得簡單許多。&lt;br>
為什麼呢？&lt;br>
因為按照題目的定義的話，&lt;br>
我們假設從每一列的尾巴接到下一列的頭，&lt;br>
最終就會得到一個完整的已排序陣列。&lt;br>
那麼，已排序陣列的搜尋方式，&lt;br>
我們以前已提到過了，就使用基本的&lt;strong>二元搜尋法(Binary Search)&lt;/strong> 即可。&lt;br>
(還沒弄清楚或還不知道二元搜尋法的讀者，可以&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
>&lt;strong>參見前面這篇&lt;/strong> &lt;/a>。)&lt;/p>
&lt;p>那麼我們所要做的，就只剩下&lt;strong>將matrix上的index，&lt;br>
轉為如果攤平以後對應到的陣列index即可。&lt;/strong>&lt;br>
對於matrix[i][j]來說，&lt;br>
由於有&lt;strong>m列n行，i代表從0到i(總共i+1個列)&lt;/strong> ，&lt;br>
所以前面會經過i列，共 &lt;strong>(i * n)&lt;/strong> 個數字；&lt;br>
接著要往右邊移動，&lt;br>
&lt;strong>j代表從0到j有j+1個數字&lt;/strong> ，再相加起來，&lt;br>
所以&lt;strong>matrix[i][j]是整個攤平以後的第(i * n + j + 1)個數字，&lt;br>
從0開始起算的話就是(i * n + j)。&lt;/strong>&lt;/p>
&lt;p>因此，如果我們找到某一個中間&lt;strong>index mid&lt;/strong> ，&lt;br>
要轉換成&lt;strong>i, j&lt;/strong> 的型式的話，&lt;br>
就只需要分別取&lt;strong>除以n得到的商和餘數&lt;/strong> 即可。&lt;/p>
&lt;p>依此進行二元搜尋的時候，其方式就和一般的二元搜尋一模一樣，&lt;br>
&lt;strong>若跳出迴圈則代表該目標值不存在於matrix中，則回傳false&lt;/strong> 。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/1caf4d46d0c548cea3bd1747a7fed7c8.js">&lt;/script>
&lt;p>Python的部分請不要忘記取整數除法要用雙斜線&amp;quot;//&amp;quot;。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/2e7c615280a7f64e4ba56d1d3948d8a3.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(log(mn))/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol>
&lt;li>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-56-binary-search-3-bd76049f8765?sk=9839faa7bfcc119a10b7fbbe6f40a6df" target="_blank" rel="noopener"
>&lt;strong>0240. Search a 2D Matrix II (Medium)&lt;/strong> &lt;/a>&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 56 Binary Search (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-56-binary-search-3/</link><pubDate>Thu, 26 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-56-binary-search-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 56 Binary Search (3)" />&lt;p>&lt;strong>0240. Search a 2D Matrix II (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write an efficient algorithm that searches for a value in an &lt;em>m&lt;/em> x &lt;em>n&lt;/em> matrix. This matrix has the following properties:&lt;/p>
&lt;ul>
&lt;li>Integers in each row are sorted in ascending from left to right.&lt;/li>
&lt;li>Integers in each column are sorted in ascending from top to bottom.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;p>Consider the following matrix:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [1, 4, 7, 11, 15],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [2, 5, 8, 12, 19],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [3, 6, 9, 16, 22],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [10, 13, 14, 17, 24],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [18, 21, 23, 26, 30]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Given target = &lt;code>5&lt;/code>, return &lt;code>true&lt;/code>.&lt;/p>
&lt;p>Given target = &lt;code>20&lt;/code>, return &lt;code>false&lt;/code>.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個m x n的矩陣，此矩陣每列(row)都是從左到右升冪排序；&lt;br>
同時此矩陣每行(column)都是由上到下升冪排序。&lt;br>
試找出一個有效率的演算法，&lt;br>
來處理在這個矩陣搜尋一個值是否在這裡面。&lt;/p>
&lt;p>這題乍看之下沒有這麼直觀，如果我們從matrix[0][0]出發的話，&lt;br>
顯然馬上就會碰到問題：&lt;br>
&lt;strong>「好現在target比1大，我該往哪邊走？」&lt;/strong> 看來怎麼走都不對是吧？如果透過暴力的方式來一排一排找，&lt;br>
結果時間複雜度會是&lt;strong>O(mn)&lt;/strong> 。&lt;br>
就算有想到&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
>&lt;strong>Binary Search&lt;/strong> &lt;/a>可以處理已排序的陣列，&lt;br>
每次取一行或一列來搜尋值，&lt;br>
時間複雜度也只會降到&lt;strong>O(m log n)或O(n log m)&lt;/strong> ，&lt;br>
似乎還是不那麼理想。&lt;/p>
&lt;p>那麼，該怎麼考慮這個題目呢？&lt;br>
翻了翻提示，居然也是寫Binary Search；&lt;br>
而Binary Search的精髓，&lt;br>
其實就在於可以&lt;strong>在每次的抉擇中保留需要的那部分的選項&lt;/strong> 。&lt;/p>
&lt;p>那麼，回頭看看上面的矩陣，想要能夠靠選擇每次去掉選項，&lt;br>
我們考慮看看15這個點如何？&lt;/p>
&lt;p>當&lt;strong>target等於15&lt;/strong> 的時候，就&lt;strong>直接是答案了，回傳true&lt;/strong> 。&lt;br>
當&lt;strong>target不是15&lt;/strong> 的時候，可以分成&lt;strong>比15大，或比15小&lt;/strong> 。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>比15大&lt;/strong> 的狀況：&lt;br>
代表原先15的&lt;strong>一整列(1, 4, 7, 11, 15)已經都不用考慮了&lt;/strong> ，&lt;br>
因為&lt;strong>15已經是這整列的最大值&lt;/strong> ，故我們可以挑到19，&lt;br>
因為19這行還沒看過，&lt;br>
同時(15, 19, 22, 24, 30)這當中也是越來越大，&lt;br>
所以挑選19可以繼續進行比較，&lt;br>
這個操作就相當於&lt;strong>扣掉一整列的備選&lt;/strong> 。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>比15小&lt;/strong> 的狀況：&lt;br>
代表原先15的&lt;strong>一整行(15, 19, 22, 24, 30)不用考慮了，&lt;/strong>&lt;br>
理由跟1.講得相似，只是這次我們就變成&lt;strong>往右走挑到11&lt;/strong> ，&lt;br>
整個操作相當於&lt;strong>扣掉一整行的備選&lt;/strong> 。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>我們每次刪去一行或一列，那麼總共有m列n行的話，&lt;br>
最多就要操作&lt;strong>m+n次&lt;/strong> 才能確認target是否在matrix中。&lt;br>
(因為每次扣掉一行或一列的備選嘛)&lt;/p>
&lt;p>所以其實再仔細一看，&lt;br>
如果我們將這個矩陣往逆時針轉45度，&lt;br>
(或將你的頭順時針轉45度)，&lt;br>
你會發現這整個矩陣其實可以當作一個&lt;strong>以15為根結點的二元樹&lt;/strong> 。&lt;br>
(不過由於它的特性，可以想像它還有其它不只二元樹的連結)&lt;br>
(或者更準確的說，它就是&lt;strong>有向圖(Oriented Graph)&lt;/strong> )&lt;/p>
&lt;p>所以我們的整個演算法如下：&lt;/p>
&lt;ol>
&lt;li>檢查matrix是否正常，不正常則直接回傳false&lt;/li>
&lt;li>將初始點定在**(i, j)=(0, n-1)** 的位置&lt;/li>
&lt;li>當&lt;strong>i和j都沒有超過邊界&lt;/strong> 的時候，進行下面的迴圈：&lt;br>
3-a. 若target和當前點的値&lt;strong>相等&lt;/strong> ，&lt;strong>回傳true&lt;/strong>&lt;br>
3-b. 否則&lt;strong>若target較大，將i遞增&lt;/strong>&lt;br>
3-c. 否則&lt;strong>將j遞減&lt;/strong>&lt;/li>
&lt;li>若迴圈結束尚未回傳，代表這個值不在矩陣內，&lt;br>
回傳false結束。&lt;/li>
&lt;/ol>
&lt;p>寫成程式碼如下所附。&lt;br>
(也有人判斷第一步的時候用&amp;lt; 1而非==0，但測試目前沒有明顯差異，&lt;br>
讀者依自己喜好選擇寫法即可。)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7c776ac9c439719db58ae588a14d0e6a.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/8d2f7e0afa79f5065e7fe925d98ad5c1.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(m+n)/O(1)，因為每次都會刪去一行或一列，最差狀況就是全部刪完。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
Python Taiwan 王彥珽&lt;/strong>：** 直行橫列**才對(註：中國才是橫行直列XD)&lt;br>
(但我工作就會講row跟column啦)&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>如果你／妳覺得這篇文章不錯，請給我5個拍手，並且給我5個Like。
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(點開最上面的SHOW EMBED!)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>從LeetCode學演算法 - 55 DFS (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-55-dfs-3/</link><pubDate>Mon, 23 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-55-dfs-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 55 DFS (3)" />&lt;p>&lt;strong>0236. Lowest Common Ancestor of a Binary Tree (Medium)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.&lt;/p>
&lt;p>According to the &lt;a class="link" href="https://en.wikipedia.org/wiki/Lowest_common_ancestor" target="_blank" rel="noopener"
>definition of LCA on Wikipedia&lt;/a>: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow &lt;strong>a node to be a descendant of itself&lt;/strong> ).”&lt;/p>
&lt;p>Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/image-001.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The LCA of nodes 5 and 1 is 3.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>All of the nodes’ values will be unique.&lt;/li>
&lt;li>p and q are different and both values will exist in the binary tree.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一棵二元樹，試找出樹中兩個給定的節點的最低共同祖先(LCA)。&lt;br>
整棵樹的節點值均不同，且兩個節點p, q是不同的節點，&lt;br>
且會存在於此樹上。&lt;/p>
&lt;p>由於不同於之前的&lt;a class="link" href="../learn-algorithm-from-leetcode-51-bst-4" >0235&lt;/a>題，這題是二元樹而非二元搜尋樹，&lt;br>
所以我們於此喪失了可以透過比大小來決定要往哪個方向走的可能。&lt;br>
那麼怎麼辦呢？&lt;/p>
&lt;p>對於兩個節點的最低共同祖先來說，有一個特性是絕對肯定的，&lt;br>
就是以下3點必然會&lt;strong>恰好成立2點&lt;/strong> ：&lt;br>
&lt;strong>1. 節點自己是p或q&lt;br>
2. 節點的左子樹有p或q&lt;br>
3. 節點的右子樹有p或q&lt;/strong>&lt;/p>
&lt;p>1, 2和1, 3應該很直觀，就不多作解釋了，&lt;br>
這邊有一點很重要的是，&lt;strong>當共同祖先不是p或q&lt;/strong> 的時候，&lt;br>
如果&lt;strong>p和q都分布在同一邊的子樹，那它就不會是最低共同祖先&lt;/strong> ，&lt;br>
因為我們還可以再往下找更低的共同祖先。&lt;br>
所以&lt;strong>1不成立的時候，2, 3都必須要成立才行&lt;/strong> ，&lt;br>
這樣才能符合&lt;strong>最低&lt;/strong> 的特性。&lt;/p>
&lt;p>我們可以運用&lt;strong>DFS&lt;/strong> 的方式來確認一個節點的左子樹/右子樹是否符合特性，&lt;br>
並且&lt;strong>同時判斷該節點是否是p或q之一&lt;/strong> ，&lt;br>
這樣一來，只要&lt;strong>三者成立兩點&lt;/strong> 的時候，就表示我們找到目標了，&lt;br>
可以將答案記錄下來。&lt;/p>
&lt;p>所以只要將整棵樹遍歷過一次，最後回傳記錄下來的答案即可。&lt;br>
實作上，我們將1當作成立，0當作不成立，&lt;br>
那麼整個DFS的過程就是在找三個結果相加等於2。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0dab2684ca6e2afc4d7f28ff6d183631.js">&lt;/script>
&lt;p>Python部分基本一致，只是三元運算是由if else來寫的。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/53c1a4f2fa785ceaeb9fa49f44f46035.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(N)，因為要考慮到最糟的情況，同時遞迴會產生&lt;strong>call stack&lt;/strong> )&lt;/p>
&lt;p>「能否給出迭代解？」&lt;br>
(原題的&lt;a class="link" href="https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/" target="_blank" rel="noopener"
>Solution&lt;/a>處有給出來，請參照看看XD，簡單來說，&lt;br>
就是分別使用stack記錄p跟q的祖先節點，最後回頭找最底層的那個祖先。)&lt;br>
(但因為使用stack的關係，&lt;strong>空間複雜度依舊會是O(N)&lt;/strong> )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 54 DFS (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-54-dfs-2/</link><pubDate>Sun, 22 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-54-dfs-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 54 DFS (2)" />&lt;p>&lt;strong>0114. Flatten Binary Tree to Linked List (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, flatten it to a linked list in-place.&lt;/p>
&lt;p>For example, given the following tree:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3 4 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The flattened tree should look like:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，請將其攤平成linkedlist形式且以in-place的條件進行。&lt;br>
依照題目要求攤平後，整棵樹應該會變成每一個節點只會有右邊的節點。&lt;/p>
&lt;p>仔細觀察題目我們會發現其走訪的順序其實是pre-order。(中左右)&lt;br>
那麼，該怎麼做到攤平呢？&lt;/p>
&lt;p>我們可以先考慮某個子樹的情況，&lt;br>
根節點自己在攤平後應該還是不會動，&lt;br>
&lt;strong>而所有左子樹的節點在攤平後應該都排在右子樹節點的前面&lt;/strong> 。&lt;br>
所以當我們假定先完成了一個樹的左右子樹的攤平的話，&lt;br>
樹應該長得像這樣：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>　 a
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>b e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> c f
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> d g
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>那麼，我們要做的應該是&lt;strong>將d跟e接起來(a-e斷開)&lt;/strong> ，&lt;br>
並且&lt;strong>將b的位置從a的左邊挪到右邊&lt;/strong> 。&lt;/p>
&lt;p>所以整個流程會像這樣：&lt;/p>
&lt;ol>
&lt;li>檢查&lt;strong>根節點&lt;/strong> ，是NIL則回傳(代表這條路走到底了)。&lt;/li>
&lt;li>先記錄左右節點備用(l, r)，&lt;br>
並分別&lt;strong>呼叫自己的左右節點進入flatten遞迴&lt;/strong> 。&lt;/li>
&lt;li>經過2以後左右子樹應該分別攤平了，&lt;br>
現在將&lt;strong>左節點設為null，右節點設為l&lt;/strong> 。&lt;/li>
&lt;li>使用迴圈找到&lt;strong>root.right的最右邊的節點&lt;/strong> (也就是原先左子樹的最後一個節點)，&lt;br>
將其和r接起來。(也就是在做上圖的&lt;strong>d跟e&lt;/strong> 的銜接)&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/f023fc0414c82c9e7c50441a34211153.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/004b0b352fc9107669019a4fbceac3c2.js">&lt;/script>
&lt;p>讀者可能會注意到上面也提供了迭代解，&lt;br>
這個版本的解法源自於&lt;strong>Morris Traversal&lt;/strong> ，&lt;br>
有興趣的讀者可以了解一下。&lt;/p>
&lt;p>簡單來說呢，它做的事情跟遞迴是一致的，&lt;br>
不過它不需要使用到call stack，&lt;br>
只需要用到&lt;strong>輔助的TreeNode&lt;/strong> 來記錄先前的root.right。&lt;br>
每次我們會&lt;strong>檢查左節點是否為NIL&lt;/strong> ，&lt;br>
是的話我們可以&lt;strong>直接往右邊走&lt;/strong> (因為左邊不用處理了)；&lt;br>
接著做的事情相同，先用&lt;strong>tmp暫時存下右子樹&lt;/strong> ，&lt;br>
對&lt;strong>左子樹進行接到右邊的動作。&lt;/strong> (也就是每一次會處理掉&lt;strong>每個左子樹的右邊的分枝&lt;/strong> )&lt;br>
這整個流程並不是很好理解，&lt;br>
讀者只需留意到&lt;strong>其時間複雜度一樣是O(N)&lt;/strong> 即可，&lt;br>
在實際面對類似題目時，如果沒有把握，可以以前面的遞迴解為主。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，但遞迴解的空間複雜度要另行考慮call stack，&lt;br>
若平衡的話是O(logN))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 53 Binary Search (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-53-binary-search-2/</link><pubDate>Sat, 21 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-53-binary-search-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 53 Binary Search (2)" />&lt;p>&lt;strong>0278. First Bad Version (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.&lt;/p>
&lt;p>Suppose you have &lt;code>n&lt;/code> versions &lt;code>[1, 2, ..., n]&lt;/code> and you want to find out the first bad one, which causes all the following ones to be bad.&lt;/p>
&lt;p>You are given an API &lt;code>bool isBadVersion(version)&lt;/code> which will return whether &lt;code>version&lt;/code> is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given n = 5, and version = 4 is the first bad version.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>call isBadVersion(3) -&amp;gt; false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>call isBadVersion(5) -&amp;gt; true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>call isBadVersion(4) -&amp;gt; true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Then 4 is the first bad version.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>一個正在由你主導的團隊所開發的產品在最新的版本沒過品質檢驗。&lt;br>
由於每個版本都是由前面的版本進版，所以當某個版本壞掉了，&lt;br>
其後的版本也都會是壞的。&lt;br>
假定有n個版本，你要找出第一個開始壞掉的版本。&lt;/p>
&lt;p>這題其實蠻真實的，&lt;br>
除了一般來說不會有什麼API，&lt;br>
可以看這個版本是不是壞掉這種東西(都嘛要自己測XD)&lt;br>
而實際碰到這種狀況的時候，&lt;br>
通常做的也是先想辦法倒回到某個版本時間點。&lt;br>
這時候Project Owner就會叫大家先不要commit了，&lt;br>
開始從上一個好的版本到這個版本中列出所有commits，&lt;br>
再來&lt;strong>切一半&lt;/strong> 的位置來檢查&lt;strong>中間的版本&lt;/strong> 有沒有問題，&lt;br>
&lt;strong>沒有問題&lt;/strong> 的話就代表這個&lt;strong>中間點到尾端&lt;/strong> 這區間才有問題；&lt;br>
&lt;strong>有問題&lt;/strong> 的話就代表是&lt;strong>開頭到中間點&lt;/strong> 這個區間有問題。&lt;/p>
&lt;p>所以每次我們都可以排查掉一半的可能性並縮小範圍，&lt;br>
最終就找到那個元凶的commit，視情況決定要做revert或其他動作。&lt;/p>
&lt;p>所以我們可以發現，這種連續性的東西，&lt;br>
也可以用Binary Search的方式來解，只是要處理的條件就不同了。&lt;/p>
&lt;p>我們將較小的版本叫lo，較大的版本叫hi，&lt;br>
一開始lo=1, hi=n，取中間的版本mid，&lt;br>
&lt;strong>當mid剛好是bad version時，並不代表可以回傳mid&lt;/strong> ，&lt;br>
應該&lt;strong>將hi設定為mid&lt;/strong> (也就是&lt;strong>可能的範圍是1~mid&lt;/strong> )。&lt;br>
&lt;strong>否則的話，代表1~mid都是清白的&lt;/strong> ，&lt;br>
我們可以將&lt;strong>lo設定為mid+1&lt;/strong> ，縮小範圍繼續搜尋。&lt;/p>
&lt;p>最終，當lo和hi交會的時候，&lt;br>
代表我們找到出問題的那個版本，所以&lt;strong>最後要回傳lo&lt;/strong> 。&lt;/p>
&lt;p>Java的部分考慮到int要盡量避免溢位，&lt;br>
一樣使用lo + (hi - lo) / 2的形式來計算。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/5c120ea7be03505b933dcc4778f7a6ec.js">&lt;/script>
&lt;p>Python的部分一樣請記得要整數除法。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/6b2a95179dcefc6dd9e3013798a4a37b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(logN)/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
>&lt;strong>0035. Search Insert Position&lt;/strong> &lt;/a>2.&lt;a class="link" href="https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/" target="_blank" rel="noopener"
>&lt;strong>0034. Find First and Last Position of Element in Sorted Array&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 52 Array (11)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-52-array-11/</link><pubDate>Fri, 20 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-52-array-11/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 52 Array (11)" />&lt;p>&lt;strong>0268. Missing Number (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array containing &lt;em>n&lt;/em> distinct numbers taken from &lt;code>0, 1, 2, ..., n&lt;/code>, find the one that is missing from the array.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [3,0,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [9,6,4,2,3,5,7,0,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 8
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note&lt;/strong> :&lt;br>
Your algorithm should run in linear runtime complexity. &lt;br>
Could you implement it using only constant extra space complexity?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個陣列內含n個不同的數字，&lt;br>
(從0~n之間選n個，也就是說會少一個)&lt;br>
試找出漏掉的那個數。&lt;/p>
&lt;p>首先最笨最暴力的方法當然是排序過後再從0開始看nums[i]是否為i。&lt;br>
這個做法顯然經過排序就需要O(NlogN)的時間，&lt;br>
但其實還是可以通過測資XD&lt;/p>
&lt;p>我們考慮比較簡單一點的作法：&lt;br>
我們都知道梯形公式(以及那個聰明的高斯XD)，&lt;br>
從0加到n的總和會是n * (n+1) / 2。&lt;/p>
&lt;p>所以想要知道中間漏掉哪個，就將0~n的總和，&lt;br>
減去nums的所有元素全部加起來即可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/f2d47f7e55b9e3b9cda2a112ef414d87.js">&lt;/script>
&lt;p>在Python中不要忘記了除法取整數要用「//」，&lt;br>
並且陣列的和可以用sum來取得。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c956cdd9bc2f5d83735716cdaacb7dea.js">&lt;/script>
&lt;p>這種解法要留意一點，如果在有限制int的狀態下，&lt;br>
n*(n+1)是有機會溢位的！所以如果有時間的話，&lt;br>
還是可以嘗試一下下面提到的解法。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1)，乘法只做一次，加法會做n次，儲存的部分只有幾個輔助的變數)&lt;/p>
&lt;p>「這題有別的解法嗎？」&lt;br>
(其實用Bitwise Operation來解也很簡單，&lt;br>
這邊留給讀者可以自行嘗試看看(用XOR)。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 51 BST (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-51-bst-4/</link><pubDate>Tue, 17 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-51-bst-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 51 BST (4)" />&lt;p>&lt;strong>0235. Lowest Common Ancestor of a Binary Search Tree (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.&lt;/p>
&lt;p>According to the &lt;a class="link" href="https://en.wikipedia.org/wiki/Lowest_common_ancestor" target="_blank" rel="noopener"
>definition of LCA on Wikipedia&lt;/a>: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow &lt;strong>a node to be a descendant of itself&lt;/strong> ).”&lt;/p>
&lt;p>Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/image-001.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The LCA of nodes 2 and 8 is 6.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>All of the nodes’ values will be unique.&lt;/li>
&lt;li>p and q are different and both values will exist in the BST.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元搜尋樹及其中兩個不同的節點，&lt;br>
試找出它們的最近共同祖先(LCA)。&lt;/p>
&lt;p>題目有標註說一個節點可以視作自己的後裔(descendant)，&lt;br>
這點會有影響，還請留意。&lt;/p>
&lt;p>那麼，我們如何尋找這個最近共同祖先呢？&lt;br>
首先要知道，這是一棵二元搜尋樹，假設這個LCA的節點叫作L好了，&lt;br>
兩個節點分別叫p跟q，那麼我們可以考慮以下幾個狀況：&lt;/p>
&lt;ol>
&lt;li>如果L&lt;strong>是p或q其中之一&lt;/strong> 的話，&lt;strong>先遇到誰，就代表誰是那個LCA&lt;/strong> 。&lt;br>
(因為先遇到的節點會是後面的那個節點的祖先)&lt;/li>
&lt;li>如果&lt;strong>L不是p或q其中之一&lt;/strong> 的話，&lt;strong>L的値的範圍必在p.val和q.val之間&lt;/strong> ，&lt;br>
也就是說兩者會位在L的不同側的子樹。&lt;br>
(即p.val &amp;lt; L.val &amp;lt; q.val或p.val &amp;gt; L.val &amp;gt; q.val)&lt;/li>
&lt;/ol>
&lt;p>如果從root開始判斷的話，就可以分成幾種情況：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>root的値和p或q的值相等&lt;/strong> =&amp;gt; ** 直接回傳root** (p或q就是L)&lt;/li>
&lt;li>&lt;strong>root的値在p和q的值的範圍之內&lt;/strong> =&amp;gt; ** 直接回傳root**&lt;br>
(即&lt;strong>p.val &amp;lt; L.val &amp;lt; q.val&lt;/strong> 或&lt;strong>p.val &amp;gt; L.val &amp;gt; q.val&lt;/strong> )&lt;/li>
&lt;li>p和q的値都&lt;strong>小於&lt;/strong> root的值 =&amp;gt; 往下找&lt;strong>root.left&lt;/strong> 的狀況遞迴&lt;/li>
&lt;li>p和q的値都&lt;strong>大於&lt;/strong> root的值 =&amp;gt; 往下找&lt;strong>root.right&lt;/strong> 的狀況遞迴&lt;/li>
&lt;/ol>
&lt;p>也就是說，最終總會找到&lt;strong>L是p或q之一&lt;/strong> ，或者&lt;strong>L能將兩個節點拆成兩邊&lt;/strong> 。&lt;br>
於是我們可以輕鬆解出這個題目，在Python的部分，&lt;br>
除了要留意a &amp;lt; b &amp;lt; c這種形式是Python才能用的，Java不接受以外，&lt;br>
這邊在Java的解答中要提供一個較簡潔的解法。&lt;/p>
&lt;p>仔細思考的話，我們可以發現1, 2其實可以看作一件事情：&lt;br>
root.val - p.val和root.val - q.val的關係。&lt;br>
當符合&lt;strong>1.&lt;/strong> 的時候，上面的兩個式子&lt;strong>會有一個等於0&lt;/strong> ；&lt;br>
當符合&lt;strong>2.&lt;/strong> 的時候，上面的兩個式子&lt;strong>會一正一負&lt;/strong> 。&lt;br>
所以&lt;strong>兩者相乘&lt;/strong> 時，符合1.跟2.的條件的狀況下，&lt;br>
&lt;strong>結果會&amp;lt;=0 (或&amp;lt;1，因為值是int)。&lt;/strong>&lt;/p>
&lt;p>同時，當不符1.且不符2.時，&lt;strong>由於p, q已經確定是同邊&lt;/strong> 了，&lt;br>
只需要拿p來比較即可，不用再去比較q。&lt;/p>
&lt;p>根據上面的推導我們可以寫成Java的答案版本。&lt;br>
同時，由於每次遞迴都只有動到root所指向的節點，&lt;br>
所以我們也可以很簡單地將其改動成迭代的解法，&lt;br>
由於不需call stack，總體速度有可能會有些許的加快。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/106c3e2be26fd82442e842490f20a1e6.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/40c2247b1ea27812df45271cb20aa9f9.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(Worst case: O(N)/O(N) (如果節點都在同一邊)&lt;br>
平衡樹的話最大會走到整個深度的節點，是O(logN))&lt;br>
(用迭代解的話，因為不用call stack，空間複雜度為O(1))&lt;/p>
&lt;p>「用相乘的方法會有什麼副作用？」&lt;br>
(在有限定變數是int的狀況下，&lt;strong>相乘有機會導致溢位&lt;/strong> ，所以如果這題的測試資料刁鑽一點的話，請不要用相乘的，一組一組判斷就好。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/" target="_blank" rel="noopener"
>&lt;strong>0236. Lowest Common Ancestor of a Binary Tree&lt;/strong> &lt;/a>(如果這棵樹只是&lt;strong>二元樹&lt;/strong> 而非二元搜尋樹呢？)&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 50 Tree (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-50-tree-9/</link><pubDate>Sun, 15 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-50-tree-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 50 Tree (9)" />&lt;p>&lt;strong>0226. Invert Binary Tree (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Invert a binary tree.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;p>Input:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 7
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1 3 6 9
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Output:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 7 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>9 6 3 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Trivia:&lt;/strong>&lt;br>
This problem was inspired by &lt;a class="link" href="https://twitter.com/mxcl/status/608682016205344768" target="_blank" rel="noopener"
>this original tweet&lt;/a> by &lt;a class="link" href="https://twitter.com/mxcl" target="_blank" rel="noopener"
>Max Howell&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>&lt;em>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>&lt;/p>
&lt;/blockquote>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求反轉一個二元樹。&lt;/p>
&lt;p>我們今天來看一題經典的題目，&lt;br>
這題經典的原因也許不是在於它有多困難，&lt;br>
而是在於這問題背後的故事XD&lt;/p>
&lt;p>或許另一方面也可以看看他本人在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"
>回應&lt;/a>。&lt;br>
所以演算法很重要有沒有XDD&lt;br>
(據稱有一種說法是說當時的題目是要求min-max的反轉，這邊暫不討論，&lt;br>
我們以左右反轉為準)&lt;/p>
&lt;p>相信大家經過前面的一堆二元樹相關題目以後，&lt;br>
應該已經對二元樹駕輕就熟了，應該可以輕鬆地寫出遞迴方式的版本。&lt;/p>
&lt;p>跟之前的Symmetric Tree相似，&lt;br>
只是這次我們直接將一棵樹的左右節點交換，&lt;br>
除了交換以外，它們的左右子樹的部分也要再度進行交換。&lt;/p>
&lt;p>所以我們會拆成：&lt;/p>
&lt;ol>
&lt;li>檢查root是不是null (是的話代表這條路到底了，直接回傳null)&lt;/li>
&lt;li>將root.left和root.right進行交換&lt;/li>
&lt;li>將root.left和root.right分別做為參數，呼叫函式進行遞迴&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c206e5d6332ba13462b890d8cf21c256.js">&lt;/script>
&lt;p>Python寫得再簡單一點，不過意思是一樣的XD&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c206e5d6332ba13462b890d8cf21c256.js">&lt;/script>
&lt;p>你以為這樣就結束了嗎？&lt;br>
我們將繼續來探討一下如果是迭代解的話該怎麼處理。&lt;/p>
&lt;p>如果思考一下前面的遞迴解，&lt;br>
會發現一件事情：&lt;br>
&lt;strong>對於一個我們造訪的節點而言，&lt;br>
我們所影響到的只有其左節點和右節點，&lt;/strong>&lt;br>
當下這個節點的値並不會受任何影響。&lt;br>
所以我們只需要保證當走到這個節點的時候，&lt;br>
&lt;strong>關於這個節點以上的操作已經做完&lt;/strong> 即可，&lt;br>
那麼要保證這點的話，只要使用&lt;strong>level order&lt;/strong> 的方式，&lt;br>
我們按順序操作即可做完所有反轉的動作。&lt;/p>
&lt;p>由於是先將同一層的做完才會進到下一層，&lt;br>
也可以視作是BFS的方式。&lt;br>
按順序作的話，&lt;br>
可以使用Queue來處理這樣子的問題，步驟大致上是：&lt;br>
0. 檢查root是否為NIL，是的話直接回傳NIL&lt;/p>
&lt;ol>
&lt;li>建立一個queue(python請用&lt;strong>deque&lt;/strong> )&lt;/li>
&lt;li>將root放入queue中&lt;/li>
&lt;li>每次從queue中取出一個節點，將其&lt;strong>左右位置互換&lt;/strong> ，&lt;br>
並分別將&lt;strong>左右節點中非NIL的節點放入queue中&lt;/strong>&lt;/li>
&lt;li>重複3直到queue中沒有節點&lt;/li>
&lt;li>回傳root&lt;/li>
&lt;/ol>
&lt;p>Java:&lt;/p>
&lt;script src="https://gist.github.com/Desolve/ed93a54c714a8242e4df6a93f8986b2a.js">&lt;/script>
&lt;p>Python:&lt;/p>
&lt;script src="https://gist.github.com/Desolve/78234534e829f23362fc44e4b2b5c32f.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(因每個節點均要和另一個位置進行對調，所以時間複雜度為O(N)。&lt;br>
空間複雜度會受到樹的平衡程度影響。&lt;br>
&lt;strong>平衡狀態&lt;/strong> 的話空間複雜度對遞迴解來說是&lt;strong>O(logN)(call stack)&lt;/strong> ，&lt;br>
而對迭代解來說是&lt;strong>O(N)&lt;/strong> (因為最大是最底部那層)&lt;br>
(這時候反而越不平衡每層的節點會越不容易太多))&lt;/p>
&lt;p>「這兩種解哪種是DFS？哪種是BFS？」&lt;br>
(遞迴解是DFS(一路走到最深才回頭)，迭代解是BFS(當層走完才往下層走))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 49 Hash Table (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-49-hash-table-3/</link><pubDate>Fri, 13 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-49-hash-table-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 49 Hash Table (3)" />&lt;p>&lt;strong>0217. Contains Duplicate (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of integers, find if the array contains any duplicates.&lt;/p>
&lt;p>Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,1,1,3,3,4,3,2,4,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個整數陣列，若陣列有任何重複的數，則回傳true，否則回傳false。&lt;/p>
&lt;p>今天來點簡單的，畢竟中秋節嘛XD&lt;br>
和之前找出單一元素的題目不同，因為這題&lt;strong>沒有限定重複出現的次數&lt;/strong> ，&lt;br>
所以並&lt;strong>不適用於bitwise operation&lt;/strong> 的方法。&lt;/p>
&lt;p>&lt;strong>以暴力法來說要O(N²)，排序後再比要O(NlogN)&lt;/strong> ，&lt;br>
均不理想，所以一般常見的想法是，&lt;br>
一樣引入&lt;strong>hashmap或dictionary&lt;/strong> 來解題。&lt;/p>
&lt;p>而由於我們&lt;strong>只在意數字有沒有出現&lt;/strong> ，對於Java來說，&lt;br>
還有另外一個名為&lt;strong>HashSet&lt;/strong> 的方式可以使用。&lt;br>
HashSet在&lt;strong>新增&lt;/strong> 方面複雜度同於HashMap均為&lt;strong>O(1)&lt;/strong> ，&lt;br>
但HashSet同時具備Set的特性，&lt;strong>同個資料只能出現在Set當中一次&lt;/strong> ，&lt;br>
&lt;strong>若有相同資料要被新增時，則新增會失敗(回傳false)&lt;/strong> ；&lt;br>
我們可以利用這點，每次對HashSet新增當前的數字，&lt;br>
失敗則代表已經出現重複了(直接回傳true)，&lt;br>
若全數新增完畢則代表不存在重複(回傳false)。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9791e4834086d6a3371a0a63bc5ce763.js">&lt;/script>
&lt;p>&lt;strong>Python的set新增時碰到重複的資料時不會進行任何動作&lt;/strong> ，&lt;br>
所以這邊還是使用dictionary。&lt;br>
另一種作法是可以使用set來進行化簡後，&lt;strong>直接檢查總長度是否改變&lt;/strong> ，&lt;br>
即可知道是不是含有重複的元素。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/6c83c12c7d02d3eb6390f8765db211a4.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)，因為每次插入均為O(1))&lt;/p>
&lt;p>「如果限制不用HashSet/Dictionary，但給你nums值的範圍呢？」&lt;br>
(建立一個array/list，總長為整個範圍，&lt;br>
將其拿來做為輔助陣列使用即可。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 48 Trie (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/</link><pubDate>Wed, 11 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 48 Trie (1)" />&lt;p>&lt;strong>0819. Most Common Word (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a paragraph and a list of banned words, return the most frequent word that is not in the list of banned words. It is guaranteed there is at least one word that isn’t banned, and that the answer is unique.&lt;/p>
&lt;p>Words in the list of banned words are given in lowercase, and free of punctuation. Words in the paragraph are not case sensitive. The answer is in lowercase.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>paragraph = &amp;#34;Bob hit a ball, the hit BALL flew far after it was hit.&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>banned = [&amp;#34;hit&amp;#34;]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;ball&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#34;hit&amp;#34; occurs 3 times, but it is a banned word.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;#34;ball&amp;#34; occurs twice (and no other word does), so it is the most frequent non-banned word in the paragraph.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Note that words in the paragraph are not case sensitive,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>that punctuation is ignored (even if adjacent to words, such as &amp;#34;ball,&amp;#34;),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>and that &amp;#34;hit&amp;#34; isn&amp;#39;t the answer even though it occurs more because it is banned.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>1 &amp;lt;= paragraph.length &amp;lt;= 1000&lt;/code>.&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= banned.length &amp;lt;= 100&lt;/code>.&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= banned[i].length &amp;lt;= 10&lt;/code>.&lt;/li>
&lt;li>The answer is unique and written in lowercase (even if its occurrences in &lt;code>paragraph&lt;/code> may have uppercase symbols, and even if it is a proper noun.)&lt;/li>
&lt;li>&lt;code>paragraph&lt;/code> only consists of letters, spaces, or the punctuation symbols &lt;code>!?',;.&lt;/code>&lt;/li>
&lt;li>There are no hyphens or hyphenated words.&lt;/li>
&lt;li>Words only consist of letters, never apostrophes or other punctuation symbols.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個段落和一個被禁止的字的列表，回傳這個段落裡面出現次數最高且沒有在禁止字列表內的字。&lt;br>
(題目保證至少有一個字不會被禁止且答案只會有一個)&lt;/p>
&lt;p>禁止字表會以小寫字給定且不需考慮標點符號，&lt;br>
在段落中的字並不限定大小寫(也就是視作相同的字)，&lt;br>
答案要用小寫表示。&lt;/p>
&lt;p>這題一般而言會使用HashMap或dict來解題，&lt;br>
但隨著總字數的增加，一些重複的字母不斷出現感覺其實相對浪費，&lt;br>
所以今天就要專門來介紹一個資料結構來解決這個問題，&lt;br>
這個資料結構就是字典樹(Trie)。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001.png"
width="250"
height="234"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001_hud424cb306fd4066998f2ccb01b2ccff4_14207_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001_hud424cb306fd4066998f2ccb01b2ccff4_14207_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="256px"
>&lt;/p>
&lt;p>Trie (From Wikipedia)&lt;/p>
&lt;p>字典樹長得基本上就是樹的一種，通常儲存的是字串。&lt;br>
其&lt;strong>根節點代表著空字串&lt;/strong> ，而每個連結出去的節點，&lt;br>
都代表在前面的基礎上&lt;strong>加上一個字元(char)&lt;/strong> 。&lt;br>
換句話說，我們只要知道從根到葉走了哪些鏈結，&lt;br>
就知道最終葉所代表的字串是什麼，如上圖所示。&lt;/p>
&lt;p>在這題當中，我們可以自行定義一個class TrieNode，&lt;br>
當中包含了&lt;strong>links&lt;/strong> (從這個節點連出去26個字母)，&lt;br>
&lt;strong>cnt&lt;/strong> (這個字在整個段落出現的次數)，以及&lt;strong>word&lt;/strong> (實際上這個字是什麼)。&lt;/p>
&lt;blockquote>
&lt;p>其實word可以如上面所說一步一步加起來，&lt;br>
不過寫起來稍微麻煩一點點，這邊就讓我偷懶一下吧XD&lt;/p>
&lt;/blockquote>
&lt;p>在Java的部分，設定條件是：&lt;br>
當被要求大多數的字串處理函式都禁止使用時，&lt;br>
該怎麼一步一步寫出我們所要的東西。&lt;/p>
&lt;p>首先要建TrieNode，除了上面所述外，我們需要三個函式：&lt;/p>
&lt;p>&lt;strong>1. insert&lt;/strong>&lt;br>
透過每個字母沿links的路徑走，&lt;br>
如果&lt;strong>curr.links[index] == null&lt;/strong> 則表示前面還沒走過，&lt;br>
要自行new出來，並設定其word變數。&lt;br>
在走到底的時候我們要將&lt;strong>cnt數加1&lt;/strong> 。&lt;br>
(代表這個word出現在段落裡次數加1次)&lt;/p>
&lt;p>行走的路徑如之前提過的，直接&lt;strong>使用字元來減去’a’&lt;/strong> 即可，&lt;br>
這邊將&lt;strong>links[0]視為是’a’，而links[25]視為是’z’&lt;/strong> 。&lt;br>
當走到某一條links[index]還沒初始化時，&lt;br>
就將其初始化並給定其word值。&lt;br>
每次往下走時&lt;strong>不要忘記將用來迭代到下一個字元的curr指到下一個位置&lt;/strong> 。&lt;/p>
&lt;p>&lt;strong>2. ban&lt;/strong>&lt;br>
只要將該string對應的TrieNode中的&lt;strong>cnt設成零&lt;/strong> 即可。&lt;br>
如果在走的路徑途中遇到null，表示段落裡不存在這個string，&lt;br>
直接return即可。&lt;/p>
&lt;p>&lt;strong>3. findMax&lt;/strong>&lt;br>
&lt;strong>遍歷所有TrieNode並找到最大的cnt及對應的word。&lt;/strong>&lt;br>
(這邊使用到&lt;strong>res作為結果&lt;/strong> 的字串及&lt;strong>maxcnt作為儲存當前最大值的變數&lt;/strong> )&lt;br>
只需要從root的位置開始，往下搜尋有cnt的值，&lt;br>
一一比較即可，當這層搜尋完時，&lt;br>
我們還要往下一層去，所以用迴圈往下再進行遞迴。&lt;br>
(這部分是&lt;strong>DFS&lt;/strong> )&lt;/p>
&lt;p>回到&lt;strong>mostCommonWord&lt;/strong> 函式中，&lt;br>
我們先產生一個&lt;strong>StringBuilder(命名為st)&lt;/strong> 及一個&lt;strong>root(TrieNode)&lt;/strong> ，&lt;br>
並用&lt;strong>isString&lt;/strong> 來表示現在st是否構成一個word。&lt;br>
每次將paragraph中的字元取出來，檢查其是否是大小寫字母，&lt;br>
並將字母統一成小寫後接到st上；&lt;br>
一旦發現&lt;strong>遇到非大小寫字母的字元，且設定的isString為真&lt;/strong> ，&lt;br>
則表示現在st構成一個word，將其丟進root中插入到字典樹內。&lt;br>
(&lt;strong>不要忘記最後面還要再檢查一次&lt;/strong> ，&lt;br>
因為有可能還沒插入就離開迴圈了)&lt;br>
接著再&lt;strong>ban&lt;/strong> 及&lt;strong>findMax&lt;/strong> 後，就可以回傳&lt;strong>res&lt;/strong> 作為答案了!&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/5a957c601c54e428ebf3a84523a34694.js">&lt;/script>
&lt;p>Python的部分思路跟Java相近，&lt;br>
不過因直譯器的特性，這邊選擇將對應的函式拉到class Solution來做。&lt;br>
讀者可以兩邊互相對照看看差異。&lt;br>
此外，由於banned測資似乎存在會重複的狀況，&lt;br>
所以可以使用set來縮小總長。&lt;/p>
&lt;p>另這邊也提供leetcode上lee215的解：&lt;br>
使用&lt;strong>re.findall&lt;/strong> ，用正規表示式直接將words找出，&lt;br>
再利用Counter直接計算頻率，最終取出最高頻率的字。&lt;br>
(應該是目前最快的解法)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/ff1fdb1e33d75ce7a991d3e4eb21ba20.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
可以從不同面向來考慮。由於有點長，且不好解釋，&lt;br>
這邊直接貼筆者在leetcode上回答的內容。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001.png"
width="250"
height="234"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001_hud424cb306fd4066998f2ccb01b2ccff4_14207_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-48-trie-1/image-001_hud424cb306fd4066998f2ccb01b2ccff4_14207_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="256px"
>&lt;/p>
&lt;p>「這個解法有沒有再更優化的方法？」&lt;br>
(至少有兩個，如果讀者有興趣的話可以嘗試看看：&lt;/p>
&lt;ol>
&lt;li>將word的部分去除(也就是只使用中間的鏈結來取得整個字)&lt;/li>
&lt;li>其實可以&lt;strong>先做ban再作insert&lt;/strong> (ban可將cnt設為**-1** ，而insert時先檢查cnt是否為-1，是的話可以直接跳過)&lt;br>
(這個方法可以同步在insert時更新res和maxcnt，所以會變成先ban再insert完以後，就可以直接回傳答案了，速度應該會再快一點點。))&lt;/li>
&lt;/ol>
&lt;p>「Java如果允許使用split呢？」&lt;br>
(可以這樣用：&lt;br>
&lt;strong>String[] words = paragraph.toLowerCase().split(“[ !?’,;.]+”);&lt;/strong> 當然，前提是你不要中間的標點符號漏打XD)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 47 Array (10)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-47-array-10/</link><pubDate>Mon, 09 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-47-array-10/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 47 Array (10)" />&lt;p>&lt;strong>0204. Count Primes (Easy)&lt;/strong>&lt;/p>
&lt;p>(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Count the number of prime numbers less than a non-negative number, *&lt;strong>n&lt;/strong> *.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個非負整數n，試求所有小於這個n的質數。&lt;/p>
&lt;p>讓我們來複習一下國中(還是國小？)數學：&lt;br>
質數的定義就是除了&lt;strong>1和自己&lt;/strong> 以外，沒有其他數可以整除它的正整數。&lt;/p>
&lt;p>透過這個特點我們可以再延伸：&lt;br>
因為合成數必然可以拆成&lt;strong>質數相乘&lt;/strong> ，&lt;br>
所以我們要判定某個數是否是質數的話，&lt;br>
只要將&lt;strong>其他比它小的質數&lt;/strong> 測試它&lt;strong>是否是目標的因數&lt;/strong> 即可。&lt;/p>
&lt;p>另外，由於一個數若能拆成2數相乘，&lt;br>
那麼&lt;strong>其中一個因數會小於等於這個數的開根號&lt;/strong> ；&lt;br>
&lt;strong>另一個因數則是大於等於這個數的開根號&lt;/strong> 。&lt;br>
如此一來，我們只要檢驗2**~目標數的開根號** 的數是否能&lt;strong>整除目標數&lt;/strong> 即可。&lt;/p>
&lt;p>所以老師會教你一個消去法：&lt;br>
首先將2的倍數排除掉，再將3的倍數排除掉，&lt;br>
再將5的倍數排除掉……(2倍以上，不含自己)&lt;br>
一個個操作，&lt;strong>走到沒有被排除掉的數即為質數&lt;/strong> 。&lt;/p>
&lt;p>我們可以再進一步處理一點：&lt;br>
假設現在處理到i，&lt;br>
那麼其實我們應該知道&lt;strong>i*2, i*3, …, i*(i-1&lt;/strong> )的部分，&lt;br>
應該都被前面的操作&lt;strong>排除&lt;/strong> 了，&lt;br>
故每次我們只要從&lt;strong>i*i開始，排除到n，&lt;br>
也就是i走到最大n的開根號&lt;/strong>即可。&lt;/p>
&lt;p>故整個程式會從2到根號n，每次將對應i的i倍以上的部分設為非質數，&lt;br>
最後計算總質數有多少個。&lt;/p>
&lt;p>Java的部分，由於boolean預設為false，&lt;br>
這邊使用nPrime代表not prime，所以nPrime為false代表這個數是質數，&lt;br>
要設定成不是質數時請用nPrime[j] = true。&lt;br>
在處理完後請記得bound後面的質數個數要記得加起來。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/249749ca7fc24c38e1573803cba598c1.js">&lt;/script>
&lt;p>Python的部分，sqrt可以直接用n ** 0.5，&lt;br>
並且我們可以用1代表質數，0代表非質數，&lt;br>
讀者可以仔細看一下第8行，其實和Java迴圈的目的是一樣的，&lt;br>
不過這邊直接最後才算prime陣列的總和來取得質數個數。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/998546f5800bc10c64ad1e0cc240c4a3.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n), O(&lt;em>n&lt;/em> log log &lt;em>n&lt;/em>))&lt;br>
(外層迴圈的boundary上限是sqrt(n)，&lt;br>
內層j的次數上限會從n/2 -&amp;gt; sqrt(n)，具體計算我也不會XD&lt;br>
以Wikipedia提供的時間複雜度為O(&lt;em>n&lt;/em> log log &lt;em>n&lt;/em>)。&lt;br>
&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5%B0%BC%E7%AD%9B%E6%B3%95" target="_blank" rel="noopener"
>https://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5%B0%BC%E7%AD%9B%E6%B3%95&lt;/a>)&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
Python Taiwan, 林宣丞：&lt;strong>此篩選方式又稱&lt;/strong> 埃拉托斯特尼篩法&lt;/strong>(sieve of Eratosthenes)。&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>如果你／妳非常喜歡這篇文章，可以按著拍手直到50下。
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>也請記得「Follow」我，隨時收看最新的文章。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>從LeetCode學演算法 - 46 BFS (2) / Queue (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-46-bfs-2-queue-3/</link><pubDate>Sat, 07 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-46-bfs-2-queue-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 46 BFS (2) / Queue (3)" />&lt;p>&lt;strong>0199. Binary Tree Right Side View (Medium)&lt;/strong>&lt;/p>
&lt;p>&lt;strong>另外筆者昨天生日，快補祝我生日快樂XDDDDD&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, imagine yourself standing on the &lt;em>right&lt;/em> side of it, return the values of the nodes you can see ordered from top to bottom.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,null,5,null,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1, 3, 4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1 &amp;lt;---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2 3 &amp;lt;---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 5 4 &amp;lt;---
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一棵二元樹，想像你站在樹的右邊往左看，&lt;br>
試回傳從上到下依序所看到的值。&lt;/p>
&lt;p>這題一看就知道某種程度上屬於level-order traversal，&lt;br>
(還不清楚或不知道什麼是level-order的讀者請參閱&lt;a class="link" href="../learn-algorithm-from-leetcode-43-bfs-1-queue-2" >這篇&lt;/a>)&lt;br>
只是要求的部分有點不一樣而已，這邊只要求最右邊的數字。&lt;/p>
&lt;p>那麼要注意囉！可能會有人想，我能不能&lt;strong>只走最右邊&lt;/strong> 取值就好呢？&lt;br>
答案是當然不行！！！因為你可能會遇到類似這樣的狀況：&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-46-bfs-2-queue-3/image-001.png"
width="298"
height="228"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-46-bfs-2-queue-3/image-001_hu22938699d7cce030a4742cc20646a20d_11109_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-46-bfs-2-queue-3/image-001_hu22938699d7cce030a4742cc20646a20d_11109_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="130"
data-flex-basis="313px"
>&lt;/p>
&lt;p>你看到的最右邊不是人家的最右邊XD&lt;/p>
&lt;p>如果只取最右邊的話，顯然我們會走1-3-0然後就結束了，&lt;br>
但還有一個4落在中間，所以這題無論如何還是要乖乖遍歷所有節點才行。&lt;/p>
&lt;p>我們可以用BFS的方式來解這題(DFS也行，但要用到遞迴，這裡暫不討論)，步驟如下：&lt;/p>
&lt;ol>
&lt;li>先新增一個queue用來存放當層(level)的所有節點，&lt;br>
另外開一個串列res(result)用來存放結果。&lt;/li>
&lt;li>記錄當下queue的總數cnt(count)。&lt;/li>
&lt;li>執行一個cnt次數的迴圈，依序將當層的節點取出&lt;/li>
&lt;li>每取出一個節點，就分別檢查其左右節點是否存在，&lt;br>
存在則以&lt;strong>先左後右&lt;/strong> 的順序放入queue中。&lt;/li>
&lt;li>迴圈執行完後，queue中應該全是下一層的節點；&lt;br>
同時&lt;strong>最後一個取出的節點&lt;/strong> ，就是每層最右邊的節點，&lt;br>
將其值取出放入res中。&lt;/li>
&lt;li>重複2~5的動作，直到queue中沒有節點為止。&lt;/li>
&lt;/ol>
&lt;p>讀者會發現這樣的做法唯一的差別就是要&lt;strong>記錄最後一個取出的節點&lt;/strong> ，&lt;br>
其他和level-order traversal一樣，利用queue先進先出的原則，&lt;br>
每次恰好處理一層的節點。&lt;/p>
&lt;p>依此我們可以寫成程式碼，&lt;br>
Java的部分List和Queue都可以使用LinkedList，&lt;br>
且TreeNode的部分由於Java必須給定值，故一開始last先行給定為null。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/110dada57bc59c4a1eec9b141779b19f.js">&lt;/script>
&lt;p>Python的部分不要忘記當需要從左邊取值時&lt;strong>deque&lt;/strong> 的速度會較List快，&lt;br>
另外last其實可以不用先給值也可以順利通過。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/65975540d83a1c1f23de9bfa9a2c7f91.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)，每個節點都會遍歷過，&lt;br>
同時因為使用Queue的時候中間會儲存整個level，&lt;br>
空間複雜度還是跟總數相關。)&lt;/p>
&lt;p>「可以使用DFS嗎？」&lt;br>
(可以，但需要對每項記錄其level，解法相對較難處理，讀者可嘗試看看)&lt;/p>
&lt;p>「如果題目改成從左邊看呢？」&lt;br>
(一樣要遍歷所有節點，但改成在每一層的第一項就將值置入到答案中)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/binary-tree-level-order-traversal/" target="_blank" rel="noopener"
>&lt;strong>0102. Binary Tree Level Order Traversal&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 45 DFS (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-45-dfs-1/</link><pubDate>Wed, 04 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-45-dfs-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 45 DFS (1)" />&lt;p>&lt;strong>0200 Number of Islands (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a 2d grid map of &lt;code>'1'&lt;/code>s (land) and &lt;code>'0'&lt;/code>s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11110
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11010
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>00000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>00100
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>00011
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二維的地圖當中&lt;strong>陸地用'1&amp;rsquo;表示，水則用'0&amp;rsquo;表示&lt;/strong> ，&lt;br>
試計數這整張圖有多少島嶼(island)。可假定地圖的外圍均為水域。&lt;br>
(島嶼的定義就是其周圍都圍繞著水，&lt;br>
且可以通過連接相鄰的垂直/水平陸地所構成。)&lt;/p>
&lt;p>如對於題目描述依舊沒搞懂的話，就把它當成小畫家填色的色塊吧！&lt;br>
視為相同區域的用油漆桶可以全部填滿XD&lt;br>
而題目所問的，就相當於&lt;strong>要填幾次才能將所有陸地區域填滿&lt;/strong> 。&lt;/p>
&lt;p>對於要確認島嶼這點，只有一種方法：&lt;br>
每次從一個點開始向外延伸相鄰的格子，&lt;br>
直到周圍沒有可以延伸的區域為止。&lt;br>
這時候這整塊區域就是我們所謂的島嶼，於是&lt;strong>計數可以加1&lt;/strong> 。&lt;br>
那麼問題來了，在延伸的過程中一共有&lt;strong>四個方向&lt;/strong> 可以選擇，&lt;br>
如果不加限制的話，無疑會有重複的部分；&lt;br>
所以除了&lt;strong>檢查是否遇到水(‘0’，也就是可以不用繼續往下搜尋)外&lt;/strong> ，&lt;br>
我們還需要知道這個格子是否已經走過了。&lt;br>
所以我們會再&lt;strong>新增一個visited陣列用來標明已經走過的區域&lt;/strong> 。&lt;br>
(這樣子只要已經走過的就直接跳過即可。)&lt;/p>
&lt;p>由於每次會需要走到底才會回頭，&lt;br>
所以這種方式是很典型的&lt;strong>DFS(Depth-First Search，深度優先搜尋)&lt;/strong> 方法。&lt;/p>
&lt;p>所以流程會變成：&lt;/p>
&lt;ol>
&lt;li>初始化一個&lt;strong>visited&lt;/strong> 二維陣列，預設當中每個值均為&lt;strong>false&lt;/strong>&lt;/li>
&lt;li>&lt;strong>對grid中的每個點(i, j)檢查其是否為陸地(‘1’)&lt;/strong> ，且未曾走訪過的話:&lt;br>
2-a. 遞增島嶼計數值，並&lt;strong>從每個點(i, j)呼叫函式dfs&lt;/strong> 來開始走訪&lt;/li>
&lt;li>在dfs中，先檢查(i, j)點是否符合規範(因會+1或-1，&lt;strong>須不超出範圍&lt;/strong> )，&lt;br>
且&lt;strong>尚未走訪過(visited[i][j] == false)&lt;/strong> 的狀況，進行3-a的流程&lt;br>
3-a. 將&lt;strong>visited[i][j]設定為true&lt;/strong>&lt;br>
3-b. 往(i, j)的&lt;strong>上下左右&lt;/strong> 走，並傳入下一階段的dfs。&lt;/li>
&lt;/ol>
&lt;p>這麼一來，當整張圖掃過去以後，&lt;br>
我們就能知道到底有幾個島嶼了！&lt;/p>
&lt;p>Java和Python的寫法基本一致，這邊不再贅述，&lt;br>
讀者只要注意到應該被檢查的&lt;strong>邊界條件&lt;/strong> 即可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/f041abe3a9e417167c1da9dc352cafa3.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0c36e727c43bb33f4fa4a35bb83816fd.js">&lt;/script>
&lt;p>在這個範例中我們使用了一個額外的陣列來儲存，&lt;br>
有沒有辦法能夠不用額外的陣列呢？&lt;br>
其實是有的，&lt;strong>辦法就是將每次走過的陸地(‘1’)，&lt;br>
都直接設定成水(‘0’)，自然就相當於都走過了&lt;/strong>，&lt;br>
從而可以替代掉用visited來處理。&lt;br>
優點是速度會較為快速，&lt;br>
但很嚴重的缺點是這麼做完以後，&lt;br>
&lt;strong>grid本身就會變成全部都是’0&amp;rsquo;的陣列了&lt;/strong> 。&lt;br>
除非已經確定這個grid可以被任意操作，&lt;br>
否則筆者認為要這麼做的話記得要先問清楚要求才下手才行XD~&lt;/p>
&lt;p>此外，這題在返回時仍舊要&lt;strong>保留走過哪些格子的資訊&lt;/strong> ，&lt;br>
所以和之前的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-42-backtracking-1-tree-8-2f230ef087cd?source=friends_link&amp;amp;sk=55c3770b3626f512e1d1a2477f91e3a0" target="_blank" rel="noopener"
>Backtracking的題目&lt;/a>作法是不一樣的。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(若m, n為長寬，O(m*n) for best case，理論上全部走訪一遍即可, O(m*n))&lt;br>
(如果可以清空grid則記錄用的空間複雜度是O(1))&lt;br>
(若考慮call stack的部份的話，總空間複雜度worst case是&lt;strong>O(N)&lt;/strong> )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/surrounded-regions/" target="_blank" rel="noopener"
>&lt;strong>0130. Surrounded Regions&lt;/strong> &lt;/a>2.&lt;a class="link" href="https://leetcode.com/problems/max-area-of-island/" target="_blank" rel="noopener"
>&lt;strong>0695. Max Area of Island&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
Raiy Kuo&lt;/strong>: DFS時recusive占用的stack應一併考慮進去。&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 44 Linked List (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/</link><pubDate>Tue, 03 Sep 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 44 Linked List (5)" />&lt;p>&lt;strong>0160. Intersection of Two Linked Lists (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write a program to find the node at which the intersection of two singly linked lists begins.&lt;/p>
&lt;p>For example, the following two linked lists:&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-001.png"
width="742"
height="241"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-001_hude218fc274483dfdc61003530e319810_15766_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-001_hude218fc274483dfdc61003530e319810_15766_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="307"
data-flex-basis="738px"
>&lt;/p>
&lt;p>begin to intersect at node c1.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-002.png"
width="742"
height="241"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-002_hudf644de7284056a294a80daee72ff383_14965_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-002_hudf644de7284056a294a80daee72ff383_14965_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="307"
data-flex-basis="738px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: Reference of the node with value = 8
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Input Explanation: The intersected node&amp;#39;s value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-003.png"
width="622"
height="241"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-003_hu9bf7667e2f8a10f4e2737dbb4a577451_13541_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-003_hu9bf7667e2f8a10f4e2737dbb4a577451_13541_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="258"
data-flex-basis="619px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: Reference of the node with value = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Input Explanation: The intersected node&amp;#39;s value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [0,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-004.png"
width="382"
height="241"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-004_hu759f719dbe4c1a49421c04259d513239_9108_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-44-linked-list-5/image-004_hu759f719dbe4c1a49421c04259d513239_9108_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="158"
data-flex-basis="380px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: null
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The two lists do not intersect, so return null.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Notes:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>If the two linked lists have no intersection at all, return &lt;code>null&lt;/code>.&lt;/li>
&lt;li>The linked lists must retain their original structure after the function returns.&lt;/li>
&lt;li>You may assume there are no cycles anywhere in the entire linked structure.&lt;/li>
&lt;li>Your code should preferably run in O(n) time and use only O(1) memory.&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>有兩個單向連結串列，試找出其交會開始的節點。&lt;br>
如果它們彼此之間沒有相交，則回傳null。&lt;br>
(注意中提到最好時間使用O(n)且空間僅使用O(1)。)&lt;/p>
&lt;p>這題其實相當簡單，但要特別留意一點：&lt;br>
&lt;strong>就算兩個節點的值相等，也並不代表它們是同一個節點。&lt;/strong>&lt;br>
從Example 1中就可以看到這個例子，&lt;br>
節點值都是1，但並非同節點，這部分要特別留意。&lt;br>
不過我們並未特別針對ListNode去實作相等的function的狀況下，&lt;br>
直接用**==** 判斷即可。&lt;/p>
&lt;p>那麼，怎麼來找共同的交會節點呢？&lt;br>
我們可以先假設它們有一個交會點，&lt;br>
那麼list A跟list B在這個交會點(含)以後的節點數會相等。&lt;br>
(因為重合了XD)&lt;/p>
&lt;p>所以比如說A總長度是9，B總長度是6，&lt;br>
我們可以先讓&lt;strong>A從開頭走3步&lt;/strong> ，(&lt;strong>這樣才能對齊&lt;/strong> )&lt;br>
接著兩邊開始依序走訪比對走到的節點是否交會，&lt;br>
若交會則回傳；&lt;strong>若走到底還沒有看到相同的節點，&lt;br>
則回傳null(或None)。&lt;/strong>&lt;/p>
&lt;p>所以大體上的操作如下：&lt;/p>
&lt;ol>
&lt;li>設定iteA/iteB作為走訪list A/list B用的節點&lt;/li>
&lt;li>先各自走訪過一輪來取得A和B分別的長度&lt;/li>
&lt;li>長度相減，讓比較長的list的起始節點先多走相差的節點數&lt;/li>
&lt;li>同時開始第二次的走訪，一邊比對節點是否交會，&lt;br>
是則回傳該節點，不是則走到至少一邊走完為止&lt;/li>
&lt;li>若4走完尚未回傳則回傳null(表示沒有交會)&lt;/li>
&lt;/ol>
&lt;p>寫成程式碼如下。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/928504259af8be4de8e5e1da0a51fc4a.js">&lt;/script>
&lt;p>Python的部分可以寫得稍微簡潔一點，&lt;br>
留意用來遞進用的迴圈這裡的for會使用單底線，&lt;br>
因為我們只想要使用重複diff或-diff次的功能，&lt;br>
並不在意迴圈執行到第幾次。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/dfa5b6bf3008a6e184d3b9a06439e465.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)，我們共遍歷了最多兩次的list，&lt;br>
且只有額外使用到幾個輔助用的節點和變數。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/minimum-index-sum-of-two-lists/" target="_blank" rel="noopener"
>&lt;strong>0599. Minimum Index Sum of Two Lists&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 43 BFS (1) / Queue (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-43-bfs-1-queue-2/</link><pubDate>Sat, 31 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-43-bfs-1-queue-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 43 BFS (1) / Queue (2)" />&lt;p>&lt;strong>1161. Maximum Level Sum of a Binary Tree (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given the &lt;code>root&lt;/code> of a binary tree, the level of its root is &lt;code>1&lt;/code>, the level of its children is &lt;code>2&lt;/code>, and so on.&lt;/p>
&lt;p>Return the &lt;strong>smallest&lt;/strong> level &lt;code>X&lt;/code> such that the sum of all the values of nodes at level &lt;code>X&lt;/code> is ** maximal**.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-43-bfs-1-queue-2/image-001.JPG"
width="332"
height="291"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-43-bfs-1-queue-2/image-001_hu2bea82da55a19ea7c267d0c3a421aead_7077_480x0_resize_q75_box.JPG 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-43-bfs-1-queue-2/image-001_hu2bea82da55a19ea7c267d0c3a421aead_7077_1024x0_resize_q75_box.JPG 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="114"
data-flex-basis="273px"
>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,7,0,7,-8,null,null]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Level 1 sum = 1.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Level 2 sum = 7 + 0 = 7.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Level 3 sum = 7 + -8 = -1.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>So we return the level with the maximum sum which is level 2.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>The number of nodes in the given tree is between &lt;code>1&lt;/code> and &lt;code>10^4&lt;/code>.&lt;/li>
&lt;li>&lt;code>-10^5 &amp;lt;= node.val &amp;lt;= 10^5&lt;/code>&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹的根節點，若將該層(level)稱為1，&lt;br>
其子節點所在層稱為2，……以此類推，&lt;br>
嘗試找出最小的x層，這層的所有節點和是在所有層裡面&lt;strong>最大的&lt;/strong> 。&lt;/p>
&lt;p>這題其實存在不同的解法，若讀者有興趣的話也可以使用DFS的解法，&lt;br>
本篇只介紹BFS的作法。&lt;/p>
&lt;p>如果有看過先前對於&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"
>Tree的介紹&lt;/a>的話，&lt;br>
我們應該有提到過不同方式的走訪，而這題問的，&lt;br>
如果限定在迭代法解的話，就適合使用&lt;strong>層序走訪(level-order traversal)&lt;/strong> 。&lt;br>
層序走訪的概念很簡單：&lt;br>
&lt;strong>每次先走完這一層的所有節點，再走下一層的所有節點&lt;/strong> 。&lt;/p>
&lt;p>用遞迴來看的話顯然是沒辦法的，&lt;br>
因為每次往下都是&lt;strong>走往下一層&lt;/strong> (左子樹或右子樹)，&lt;br>
所以我們需要用非遞迴的方式，並使用Queue來作輔助。&lt;/p>
&lt;p>大概步驟會像這樣子：(下面將Queue命名為q)&lt;/p>
&lt;ol>
&lt;li>
&lt;p>將根節點放入q中&lt;/p>
&lt;/li>
&lt;li>
&lt;p>當q中有節點時，先求&lt;strong>q現在的節點數量cnt&lt;/strong>&lt;br>
(註：這個節點數量就是&lt;strong>目前這整層的所有節點數&lt;/strong> )&lt;/p>
&lt;/li>
&lt;li>
&lt;p>開始一個迴圈，這個&lt;strong>迴圈執行cnt次&lt;/strong> :&lt;br>
3-a. 每次從q中&lt;strong>取出一個節點n&lt;/strong> ，並&lt;strong>將其值加到當前總和total&lt;/strong> 中&lt;br>
3-b. 檢查左右節點，如果&lt;strong>不是NIL則放進q中&lt;/strong>&lt;br>
&lt;strong>(註：第3步做完以後，&lt;br>
q中前一層的cnt個節點應該已經全數移除，並加入下一層的所有節點)&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>檢查&lt;strong>total是否大於當前的最大總和&lt;/strong> ，&lt;br>
若是，則替換掉&lt;strong>最大總和&lt;/strong> 及&lt;strong>所求答案的層數&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>遞增當前的層數(level)&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>重複2~5的動作，&lt;strong>直到q中沒有任何節點為止&lt;/strong>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>由上面的步驟可知，每一次我們均藉由Queue來&lt;strong>走遍所有同一層&lt;/strong> 的節點。&lt;br>
在非樹的題目中，類似的作法是先走所有離自己一步距離的可能，&lt;br>
再往下一層去處理，由於是&lt;strong>先求廣度&lt;/strong> ，&lt;br>
這樣子的作法我們稱之為&lt;strong>廣度優先搜尋(BFS, Breadth-First Search)&lt;/strong> 。&lt;/p>
&lt;p>Java的部分，我們可以使用不同的Queue的實作方式，&lt;br>
讀者可以選用ArrayList, LinkedList或ArrayDeque。&lt;br>
(一般來說ArrayList效率會較差，&lt;br>
有人說ArrayDeque號稱比LinkedList好，&lt;br>
但筆者實測看起來沒有明顯差異XD)&lt;/p>
&lt;p>Java的Queue放入和取出的寫法是&lt;strong>offer/poll&lt;/strong> ，總數使用&lt;strong>size&lt;/strong> ，&lt;br>
檢查是否為空則用&lt;strong>isEmpty&lt;/strong> 。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/cc27cb81a0ce244b5d497f33b13096bd.js">&lt;/script>
&lt;p>Python的部分則使用前面提過的&lt;strong>deque&lt;/strong> 來處理，&lt;br>
放入和取出分別是&lt;strong>append&lt;/strong> 跟&lt;strong>popleft&lt;/strong> ，總數使用&lt;strong>len&lt;/strong> ，&lt;br>
是否為空則直接&lt;strong>拿其本體來判斷&lt;/strong> (&lt;strong>裡面是空的則會是False&lt;/strong> )&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9623824b411116f828b1c3cea78a3dfd.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)，因為會遍歷整棵樹，而空間占用最大的時候會占用最下面的一整層，所以最糟的狀況也會是O(N)。)&lt;/p>
&lt;p>「題目有告訴我們node總數最大是10^4，如果這棵二元樹是處在平衡的狀態的話，有沒有比較方便的解法？」&lt;br>
(平衡二元樹代表中間該填滿的都填滿了，&lt;br>
所以可以利用這點去算最大的層數，&lt;br>
新增一個陣列/串列來記錄某一層的總和；&lt;br>
直接利用層數來進行DFS，將走到的點的值加到對應的位置，&lt;br>
最後加總完以後再來看哪一個level總和最大。)&lt;/p>
&lt;p>「可以用DFS來解這題看看嗎？」&lt;br>
(可以，只是traversal的時候記得要傳遞層數的值，&lt;br>
並且開一個ArrayList/List來存放每層的總和。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 42 Backtracking (1) / Tree (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/</link><pubDate>Thu, 29 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 42 Backtracking (1) / Tree (8)" />&lt;p>&lt;strong>0257. Binary Tree Paths (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, return all root-to-leaf paths.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> A leaf is a node with no children.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: [&amp;#34;1-&amp;gt;2-&amp;gt;5&amp;#34;, &amp;#34;1-&amp;gt;3&amp;#34;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Explanation: All root-to-leaf paths are: 1-&amp;gt;2-&amp;gt;5, 1-&amp;gt;3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，回傳其所有根到葉的路徑。&lt;br>
這題是Easy難度的題目，剛好藉由它來講一下&lt;strong>回溯法(Backtracking)&lt;/strong> 。&lt;br>
這個題目看起來挺簡單的，如果沒有特別要求的話，寫起來也不難，&lt;br>
依照遞回的模式就可以順利解決，&lt;br>
思路大致上是&lt;strong>每走一步就將root的值串上path字串&lt;/strong> ，&lt;br>
直到左右均無節點，表示已走到葉節點了，即可將其放到結果res中。&lt;/p>
&lt;p>所以一般可能會寫成這樣：&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001.png"
width="554"
height="323"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001_hu353c72a9ea640e5c3cdbfff9420653c6_28463_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-42-backtracking-1-tree-8/image-001_hu353c72a9ea640e5c3cdbfff9420653c6_28463_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="171"
data-flex-basis="411px"
>&lt;/p>
&lt;p>可以通過但不盡理想的遞回解&lt;/p>
&lt;p>這麼做其實不盡理想，&lt;br>
因為我們會發現裡面的&lt;strong>每一個tmp其實都是使用一個新的變數&lt;/strong> ，&lt;br>
顯然這件事情會讓我們花費更多的空間(因為產生新的變數)。&lt;br>
怎麼辦呢？這時候就到了回溯法上場的時候了。&lt;/p>
&lt;p>我們之前有介紹過&lt;strong>DFS/BFS&lt;/strong> ，&lt;br>
分別代表著&lt;strong>深度優先搜尋&lt;/strong> 和&lt;strong>廣度優先搜尋&lt;/strong> ，&lt;br>
如這題前面的解法其實也可以當作DFS來看待，&lt;/p>
&lt;p>而&lt;strong>回溯法的概念又更廣泛一些&lt;/strong> ：&lt;br>
在每個階段將&lt;strong>所有可能性列出&lt;/strong> ，&lt;br>
經過檢查&lt;strong>排除&lt;/strong> 掉不可能的解後，&lt;strong>往下一個階段&lt;/strong> 進行搜尋；&lt;br>
如果這個階段的&lt;strong>所有分支均不成立&lt;/strong> ，&lt;br>
則&lt;strong>回復到上一個階段&lt;/strong> 的搜尋，並&lt;strong>取消&lt;/strong> 掉這個階段所造成的影響。&lt;br>
(過程中視要求，可在找到所有答案後才回傳，或者找到第一個答案就回傳)&lt;/p>
&lt;p>簡單來說，就是&lt;strong>一個一個試，&lt;br>
走錯了就回頭&lt;/strong>，而且記得先前** 試的痕跡要處理掉**就對了XD&lt;br>
聽起來可能還是有點抽象，我們講這題的實作方式好了。&lt;/p>
&lt;p>要進行回溯法，首先要&lt;strong>確立要處理的對象&lt;/strong> 。&lt;/p>
&lt;p>例如這題裡面最重要的是&lt;strong>節點經過的路徑&lt;/strong> ，&lt;br>
那麼我們應該可以將當前的路徑當作主要處理的對象：&lt;br>
每次在遞迴函式中應該要做的事情有：&lt;/p>
&lt;ol>
&lt;li>將當前的&lt;strong>根節點&lt;/strong> 加到&lt;strong>路徑&lt;/strong> 的ArrayList中&lt;/li>
&lt;li>如果&lt;strong>左節點&lt;/strong> 存在，遞迴進行&lt;strong>左子樹&lt;/strong> 的部分&lt;/li>
&lt;li>如果&lt;strong>右節點&lt;/strong> 存在，遞迴進行&lt;strong>右子樹&lt;/strong> 的部分&lt;/li>
&lt;li>如果&lt;strong>左右節點均不存在&lt;/strong> ，表示&lt;strong>該路徑是答案要求的其中一條&lt;/strong> ，&lt;br>
將整個路徑內的節點值按照要求的格式&lt;strong>輸出到結果res中&lt;/strong>&lt;/li>
&lt;li>走完前4步，&lt;strong>這個階段的可能性均搜索完畢&lt;/strong> ，&lt;br>
所以要回到上一個階段，這時&lt;strong>在1.的時候加入的根節點應該要被移除&lt;/strong> ，&lt;br>
因為上一個階段並沒有它。&lt;/li>
&lt;/ol>
&lt;p>可以看到在回溯法中，路徑的部分是&lt;strong>所有函式共用&lt;/strong> 的，&lt;br>
所以只要妥善處理用完後復原，即可使用一個List來處理整個樹的狀況，&lt;br>
這個List最大的占用空間就是&lt;strong>這棵樹的深度&lt;/strong> 。&lt;/p>
&lt;p>依此，我們可以寫出其程式碼。&lt;/p>
&lt;p>Java的部分，這邊用DFS來命名遞迴的函式名，&lt;br>
也可以叫getPath，可依讀者喜號命名。&lt;br>
使用StringBuilder來進行字串的整理(加上”-&amp;gt;”)，&lt;br>
以及使用ArrayList/LinkedList來處理path相關的部分。&lt;br>
(應該是用哪個都可以啦XD 題目只限定List)&lt;br>
最後不要忘記每次該階段做完要將最後一個進行移除(remove)。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/2e94391aaf8a2a5f54b587813db51366.js">&lt;/script>
&lt;p>Python的部份我們可以直接使用List來處理，&lt;br>
並且利用&lt;strong>join&lt;/strong> 的特性可以很方便地串接所有的path。&lt;br>
最後一樣不要忘記移除當階段的痕跡(&lt;strong>pop&lt;/strong> )。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/f6098638545b957af09e4e7432330adc.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(時間複雜度為O(N)(因為要掃過整棵樹)；&lt;br>
空間複雜度的部分，使用的path在平衡的狀態下複雜度是O(logN)&lt;br>
而最後的res部分如果用個數來看的話，完美的二元樹深度是O(logN)，&lt;br>
路徑數是O(N)，所以總占用空間是O(N * logN) )&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/path-sum-ii/" target="_blank" rel="noopener"
>&lt;strong>0113. Path Sum II&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 41 Hash Table (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-41-hash-table-2/</link><pubDate>Wed, 28 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-41-hash-table-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 41 Hash Table (2)" />&lt;p>&lt;strong>0242. Valid Anagram (Easy)&lt;/strong>&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;anagram&amp;#34;, t = &amp;#34;nagaram&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: s = &amp;#34;rat&amp;#34;, t = &amp;#34;car&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;br>
You may assume the string contains only lowercase alphabets.&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;br>
What if the inputs contain unicode characters? How would you adapt your solution to such case?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個字串s跟t，&lt;br>
寫出一個函式來判斷t是否是a的一個anagram(易位構詞)。&lt;/p>
&lt;p>所謂的anagram就是指將這個字串的字母搬動順序以後，&lt;br>
可以組成另一個字串的遊戲，這在很多推理小說裡都有出現過，&lt;br>
比如達文西密碼或者哈利波特XD&lt;/p>
&lt;p>那麼，怎麼確切知道s跟t是否是彼此的anagram呢？&lt;br>
我們比較幸運只需要檢查正確與否就好，所以一般常見的解法有幾個：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>排序(暴力?)法&lt;/strong>&lt;br>
既然完全是由相同的字母及相同使用字母的個數組成，&lt;br>
那就代表只要將兩個字串進行排序，最後它們會&lt;strong>長得一模一樣&lt;/strong> 。&lt;br>
但這樣作的時間複雜度為&lt;strong>O(n log n)(n為字串長)&lt;/strong> 。&lt;br>
雖然能夠通過測試，但似乎不是很理想。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Hash Table&lt;/strong> 法&lt;br>
上次我們已經介紹過了&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-39-array-8-hash-table-1-89fa9bd2832d?source=friends_link&amp;amp;sk=917a595b0687f84474a6bd93bb3e414b" target="_blank" rel="noopener"
>Hash Table&lt;/a>的概念，那麼這次我們應該也可以使用相同的方式來處理。由於題目已經告知字串僅含小寫字母，也就是a-z，&lt;br>
只要依序掃瞄過兩個字串，將字串所含每個字母的個數計算是否相等，&lt;br>
即可判定結果。&lt;br>
這麼作只需要&lt;strong>O(n)&lt;/strong> 的時間複雜度，空間部分只需要&lt;strong>O(1)&lt;/strong> 。&lt;br>
(因為是&lt;strong>26個字母&lt;/strong> ，所以陣列長是固定的)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>我們可以利用上一次提到的ASCII的方式，&lt;br>
來對&lt;strong>a-z&lt;/strong> 的部分位移到一個計數陣列的&lt;strong>0到25&lt;/strong> ，&lt;br>
同時，掃過&lt;strong>s&lt;/strong> 的時候將對應的&lt;strong>字母計數遞增&lt;/strong> ，&lt;br>
掃過&lt;strong>t&lt;/strong> 時將對應的&lt;strong>字母計數遞減&lt;/strong> ；&lt;br>
一旦有字母是遞減到&lt;strong>小於零&lt;/strong> 的話就可以直接判定s和t彼此並非anagram。&lt;/p>
&lt;p>Java的版本完整演示了上述的流程。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/37bdbfd09c7386aefa5407be26ec6e90.js">&lt;/script>
&lt;p>Python的部分這邊也可以另外使用別的方法，&lt;br>
這邊提供幾個比較簡便且複雜度一樣的方法：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>使用&lt;strong>count&lt;/strong> 跟&lt;strong>all&lt;/strong> 來計算(所以對每個字母都會分別檢查一次)&lt;br>
(all是用來判定所有會迭代的狀況是否全數為TRUE)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用&lt;strong>Counter&lt;/strong> 計算後再比較(所以會先算完全部再來檢查)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/d13d9a3d347ddfaa917f029aa4651c85.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n)/O(1))&lt;/p>
&lt;p>「如果大小寫視為相同？」&lt;br>
(使用類似Java的方式，但每個字元要先確認是否是大寫，&lt;br>
若是，先將其轉為小寫才往陣列中存放，之後的做法應該是一致的。)&lt;br>
(ASCII中A-Z是65&lt;del>90而a-z是97&lt;/del>122，可以先平移對應的相差量)&lt;/p>
&lt;p>「如果還有其他英文字母以外的字元？」&lt;br>
(將陣列改成用HashMap，&lt;br>
key存放字元，value存放出現次數。Python則用Dict即可)&lt;/p>
&lt;p>「如果大小寫視為相同，空格及標點符號要省略呢？&lt;br>
(沒錯，就跟達文西密碼的留法一樣，沒人在管標點的XD)」&lt;br>
(可以嘗試刪去不需要的，或只取英文字母的部分。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/group-anagrams/" target="_blank" rel="noopener"
>&lt;strong>0049. Group Anagrams&lt;/strong> &lt;/a>2.&lt;a class="link" href="https://leetcode.com/problems/find-all-anagrams-in-a-string/" target="_blank" rel="noopener"
>&lt;strong>0438. Find All Anagrams in a String&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 40 Array (9)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-40-array-9/</link><pubDate>Mon, 26 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-40-array-9/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 40 Array (9)" />&lt;p>&lt;strong>0238. Product of Array Except Self (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array &lt;code>nums&lt;/code> of &lt;em>n&lt;/em> integers where &lt;em>n&lt;/em> &amp;gt; 1, return an array &lt;code>output&lt;/code>such that &lt;code>output[i]&lt;/code> is equal to the product of all the elements of &lt;code>nums&lt;/code>except &lt;code>nums[i]&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [24,12,8,6]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong> Please solve it ** without division** and in O(&lt;em>n&lt;/em>).&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;br>
Could you solve it with constant space complexity? (The output array &lt;strong>does not&lt;/strong> count as extra space for the purpose of space complexity analysis.)&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個陣列nums，目標是產生一個output陣列，&lt;br>
這個output上的output[i]都相當於除了nums[i]以外其他的乘積。&lt;br>
要求不能用除法且必須在O(n)的時間完成。&lt;br>
延伸要求：用來做為輸出的output不算在額外的空間內的話，&lt;br>
是否可使用常數空間複雜度來解決此題？(即僅使用O(1)空間)&lt;/p>
&lt;p>這題如果用暴力法來解的話，&lt;br>
就是使用兩層for-loop，將每個output[i]先初始化為1，&lt;br>
再進行對其他值的相乘(也就是要乘N-1次)，&lt;br>
所需的總乘法會是N*(N-1)，故時間複雜度為O(N²)。&lt;/p>
&lt;p>這樣顯然速度不太好，我們再來考慮一下實際的情形。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>nums 2 3 4 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>res 3*4*5 2*4*5 2*3*5 2*3*4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>l 2 2*3 2*3*4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>r 3*4*5 4*5 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>假設有一個陣列是[2, 3, 4, 5]，而我們要求的結果是res，&lt;br>
按照定義我們可以先將res的結果寫出。&lt;br>
仔細觀察我們可以發現，如果將res的每項&lt;strong>拆成兩組相乘&lt;/strong> ，&lt;br>
我們可以拆分成l, r兩個陣列，&lt;br>
當中&lt;strong>l從index 1&lt;/strong> 開始&lt;strong>往後推&lt;/strong> 有數值，依序是&lt;strong>2, 2*3, 2*3*4&lt;/strong> 。&lt;br>
&lt;strong>r則從index 2&lt;/strong> 開始&lt;strong>往回推&lt;/strong> 有數值，依序是&lt;strong>5, 4*5, 3*4*5&lt;/strong> 。&lt;/p>
&lt;p>(這邊的拆分就是取明顯有&lt;strong>斷層&lt;/strong> 的部分，&lt;strong>空出來的部分為1&lt;/strong> )&lt;/p>
&lt;p>所以我們可以先將res初始化，用它&lt;strong>承載l&lt;/strong> 的部分，&lt;br>
再依次將r從1開始，把5,4,3依序乘上去一個值以後依序乘到res中，&lt;br>
這樣一來計算res的時候就只有分別經歷過兩次O(N)，&lt;br>
&lt;strong>時間複雜度會維持在O(N)。&lt;br>
同時，因為前面第一次利用了res來儲存l的部分，&lt;br>
第二次只用單個變數r來依序記錄要乘的順序，&lt;br>
故扣除res以後空間複雜度為O(1)。&lt;/strong>&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/77360ac2bf466202bd25645e0ab38a63.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4d8b366564facd0e05a0fcc2892a07e3.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N)/O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 39 Array (8) / Hash Table (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-39-array-8-hash-table-1/</link><pubDate>Sun, 25 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-39-array-8-hash-table-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 39 Array (8) / Hash Table (1)" />&lt;p>&lt;strong>1160. Find Words That Can Be Formed by Characters (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are given an array of strings &lt;code>words&lt;/code> and a string &lt;code>chars&lt;/code>.&lt;/p>
&lt;p>A string is &lt;em>good&lt;/em> if it can be formed by characters from &lt;code>chars&lt;/code> (each character can only be used once).&lt;/p>
&lt;p>Return the sum of lengths of all good strings in &lt;code>words&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: words = [&amp;#34;cat&amp;#34;,&amp;#34;bt&amp;#34;,&amp;#34;hat&amp;#34;,&amp;#34;tree&amp;#34;], chars = &amp;#34;atach&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The strings that can be formed are &amp;#34;cat&amp;#34; and &amp;#34;hat&amp;#34; so the answer is 3 + 3 = 6.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: words = [&amp;#34;hello&amp;#34;,&amp;#34;world&amp;#34;,&amp;#34;leetcode&amp;#34;], chars = &amp;#34;welldonehoneyr&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The strings that can be formed are &amp;#34;hello&amp;#34; and &amp;#34;world&amp;#34; so the answer is 5 + 5 = 10.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>1 &amp;lt;= words.length &amp;lt;= 1000&lt;/code>&lt;/li>
&lt;li>&lt;code>1 &amp;lt;= words[i].length, chars.length &amp;lt;= 100&lt;/code>&lt;/li>
&lt;li>All strings contain lowercase English letters only.&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定字串陣列words和一個字串chars，&lt;br>
如果陣列中的一個字串能被定義為good，&lt;br>
代表它是能由chars的中的字元組成(&lt;strong>每個字元最多只能使用一次&lt;/strong> )，&lt;br>
試將所有good的字串長度加總回傳。&lt;/p>
&lt;p>一般用來描述某個項目儲存多少值都會使用HashTable/HashMap，&lt;br>
對應到Python則通常可使用dictionary。&lt;br>
HashTable相關的儲存方式有搜尋為&lt;strong>O(1)&lt;/strong> 的特性，&lt;br>
和一般常見的搜尋資料結構如Binary Search Tree需要&lt;strong>O(log N)&lt;/strong> 不同，&lt;br>
原因是因為會實作hash function，令不同的值儲存的時候能夠得到不同的hash值，從而直接找到對應的位置。&lt;br>
(但當&lt;strong>hash function的選擇不好&lt;/strong> ，或儲存的東西太多時，&lt;br>
有機會發生碰撞(&lt;strong>collision)&lt;/strong> 問題，導致查找時間加長，這裡暫不討論。)&lt;/p>
&lt;p>在題目的條件限定在英文字母相關的時候或有特定長度限制時，&lt;br>
我們常可以用很簡單的方式來進行hash table/hash map的操作，&lt;br>
例如英文字母a~z只有26個，&lt;br>
如果題目和計算字母出現的次數有關聯性的話，&lt;br>
我們可以直接&lt;strong>以一個長度為26的陣列/串列來記錄&lt;/strong> 。&lt;/p>
&lt;p>以這題來說，題目所要求的檢查方式，&lt;br>
就是先確認chars裡面有&lt;strong>幾個a, 幾個b, &amp;hellip;&amp;hellip; , 幾個z&lt;/strong> ，&lt;br>
接下來對&lt;strong>每個字串&lt;/strong> 確認其組成，&lt;br>
&lt;strong>一旦組成需要的個數大於chars所擁有的，我們就可以直接跳過它&lt;/strong> ；&lt;br>
反之若每個字母所需的個數都滿足，&lt;br>
則將要回傳的結果加上這個字串的長度，&lt;br>
一直到全數檢查完畢即可回傳結果。&lt;/p>
&lt;p>下面Java的程式碼部分演示了上面所提到的步驟。&lt;br>
裡面用到語法蜜糖(Syntactic sugar)的作法，讀者應稍加掌握，&lt;br>
如for迴圈Java有提供連續從array中依序取出單個變數的寫法，&lt;br>
類似於Python中**”for word in words”** 的方式。&lt;br>
我們將check的部分獨立出來，作為檢查並回傳長度的部分，&lt;br>
一旦沒有成立，直接回傳0，若最終檢查通過則將len(word)回傳。&lt;/p>
&lt;p>之前應該也提到過char可以&lt;strong>使用ASCII的代表數字來加減&lt;/strong> ，&lt;br>
所以這邊取a到z來做為index 0到26，起始的基準點是&amp;rsquo;a&amp;rsquo;。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/6e9778a0d0f8e745c8fa0e29f3b4c74e.js">&lt;/script>
&lt;p>Python的部分，使用&lt;strong>Counter&lt;/strong> 可以很簡便的計算一個字串中的字母組成，&lt;br>
我們可以直接檢查每個key的值的大小來確認是否足夠組成，&lt;br>
但需留意Counter並&lt;strong>不會&lt;/strong> 放置沒有出現的字母的key，&lt;br>
故每次要先檢查是否dic中本來就沒有現在要檢查的key值，&lt;br>
避免發生錯誤。&lt;/p>
&lt;p>更簡便的方式是直接使用&lt;strong>count&lt;/strong> 來計算某個字母在字串裡面出現的次數。&lt;br>
這個應該是目前Python答案中跑最快的方法，&lt;br>
但可能是因為測試資料中比較常出現False的狀況，&lt;br>
&lt;strong>導致word不用每個字母都算完就結束了&lt;/strong> 。&lt;br>
不然在最糟的狀況下，word的每個字母應該都會算一次count，&lt;br>
且相同的字母在不同的位置上還會重新再算過一次；&lt;br>
雖然時間複雜度還是一樣(字串最長限定是100)，&lt;br>
&lt;strong>若整份資料比較容易是good的字居多的話，&lt;br>
並不建議用這樣子的方式操作。&lt;/strong>&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/da4447b5745070e12cdfc3b2e380d06b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(Java: O(N)/O(1)，&lt;br>
準確來說，最大要走完所有字的長度(所以應該可以說N個字*長度L)，&lt;br>
空間的部分，使用了26個字母來做為查表用的分類，&lt;br>
所以同一時間用到的只會有2組長度26的陣列及幾個暫存用變數&lt;br>
Python: 對二個解也都是 O(N)/O(1)，&lt;br>
但第二個解在最差的狀況下會每個字母都重覆掃過。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 38 Array (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-38-array-7/</link><pubDate>Fri, 23 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-38-array-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 38 Array (7)" />&lt;p>&lt;strong>0088. Merge Sorted Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two sorted integer arrays &lt;em>nums1&lt;/em> and &lt;em>nums2&lt;/em>, merge &lt;em>nums2&lt;/em> into &lt;em>nums1&lt;/em> as one sorted array.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>The number of elements initialized in &lt;em>nums1&lt;/em> and &lt;em>nums2&lt;/em> are &lt;em>m&lt;/em> and &lt;em>n&lt;/em> respectively.&lt;/li>
&lt;li>You may assume that &lt;em>nums1&lt;/em> has enough space (size that is greater or equal to &lt;em>m&lt;/em> + &lt;em>n&lt;/em>) to hold additional elements from &lt;em>nums2&lt;/em>.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>nums1 = [1,2,3,0,0,0], m = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>nums2 = [2,5,6], n = 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: [1,2,2,3,5,6]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>這題雖然相對比較無聊，&lt;br>
但merge的過程中其實蠻像merge sort的merge的，&lt;br>
所以選來讓讀者熟悉一下merge的概念，對上上篇提的應該會有幫助。&lt;/p>
&lt;p>題目給定兩個陣列及有放元素的對應長度，兩者除了未放元素的0以外，&lt;br>
其他均已排序。同時，題目也假設第一個陣列必定有足夠空間，&lt;br>
可以放入全部的元素。請嘗試將兩個陣列merge成一個排序的陣列，&lt;br>
&lt;strong>放置在第一個陣列中&lt;/strong> 。&lt;/p>
&lt;p>由於最終要放在nums1裡，我們可以先考慮會有的情形：&lt;/p>
&lt;ol>
&lt;li>n等於0：不用搬了，因為只有nums1有非0值。&lt;/li>
&lt;li>m等於0：只要把nums2的全搬過來即可&lt;/li>
&lt;li>其他：按照merge的原則，將雙方依序填入nums1中。&lt;/li>
&lt;/ol>
&lt;p>到這邊讀者可能會想到常規的merge是開一個&lt;strong>新陣列&lt;/strong> 將雙方依次比較，&lt;br>
每次將較小的值放入新陣列，最後排序完成。&lt;br>
現在說想放到nums1當然是可以，但&lt;strong>nums1前面有值&lt;/strong> ，&lt;br>
直接這麼做會蓋掉耶！那怎麼辦呢？&lt;br>
答案很簡單，我們已經知道兩邊的長度是m跟n，&lt;br>
那麼合併後的長度就會是&lt;strong>m+n&lt;/strong> ，尾端的index會是&lt;strong>m+n-1&lt;/strong> 。&lt;br>
我們只要將**「每次將較小的值放入開頭」** 改成**「每次將較大的值放入結尾」** ，最後即可達到相同的狀況。&lt;/p>
&lt;p>所以操作順序會是：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>令i, j, k分別為&lt;strong>m-1, n-1, m+n-1&lt;/strong> 2. 當&lt;strong>i和j都≥0&lt;/strong> 時：&lt;br>
 如果nums1的值比nums2的值大，&lt;br>
 將nums1的尾端放到k的位置，同時遞減i跟k以更新。&lt;br>
 如果nums1的值比nums2的值小(或相等)，&lt;br>
 將nums2的尾端放到k的位置，同時遞減j跟k以更新。&lt;br>
 &lt;strong>重複這個迴圈直到跳出，代表有一邊陣列放完了&lt;/strong> 。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>當 &lt;strong>i ≥ 0&lt;/strong> 時，表示其實我們已經做完了，所以不用任何操作。&lt;br>
(剩下nums1前面的部分，不需要再動了)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>當 &lt;strong>j ≥ 0&lt;/strong> 時，表示 i 的部分已經被用完了，&lt;br>
剩下的就是一路將 j 的對應值填入即可。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Java的部分，可以利用**”&amp;ndash;“** 讓對應index先填入以後再進行遞減，&lt;br>
步驟流程請參考上面演算方式並對照。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0bc0b39163cf830be89a382caf158c86.js">&lt;/script>
&lt;p>Python沒有++或 &amp;ndash; 這種東西，所以遞減時要乖乖的自己等於自己減一，&lt;br>
不過可以將需要遞減的寫在同一行，會稍微簡潔一點點。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/1fd9346c4e3203a7c61cb1be1db32380.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(m+n)，O(1)&lt;br>
前者是典型merge的時間，後者是因為我們只有使用常數變數，&lt;br>
其他都是原有的記憶體空間，故僅額外占用到O(1)的空間)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-4-6a631eb50da3?source=friends_link&amp;amp;sk=b93e9c626c915557269d99a6ad03862d" target="_blank" rel="noopener"
>&lt;strong>0021. Merge Two Sorted Lists (Easy)&lt;/strong> &lt;/a>2. &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-36-merge-sort-1-21dde785b0df?source=friends_link&amp;amp;sk=df2e91f82ce0fe4fb91c6866e87549dc" target="_blank" rel="noopener"
>&lt;strong>0148. Sort List (Medium)&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 37 Dynamic Programming (8)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-37-dynamic-programming-8/</link><pubDate>Thu, 22 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-37-dynamic-programming-8/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 37 Dynamic Programming (8)" />&lt;p>&lt;strong>0121. Best Time to Buy and Sell Stock (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Say you have an array for which the &lt;em>i&lt;/em>th element is the price of a given stock on day &lt;em>i&lt;/em>.&lt;/p>
&lt;p>If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.&lt;/p>
&lt;p>Note that you cannot sell a stock before you buy one.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [7,1,5,3,6,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Not 7-1 = 6, as selling price needs to be larger than buying price.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [7,6,4,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: In this case, no transaction is done, i.e. max profit = 0.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>買股票啦XD~題目給定一個陣列，第i個元素代表day i的股價。&lt;br>
如果你只被允許完成一次交易(買一次然後賣一次)，&lt;br>
嘗試找到最大的利潤為何。&lt;/p>
&lt;p>我們假定我們在某個時間點買了股票，&lt;br>
那獲得的利潤每隔一天，就會變動這兩天的差價值。&lt;br>
我們可以將當下的利潤定為cur，那麼cur不論從哪開始必定為0。&lt;br>
(當天買當天賣)&lt;/p>
&lt;p>假定有一天股價&lt;strong>低於&lt;/strong> 我們買的時候的價格，就表示我們&lt;strong>買貴&lt;/strong> 了，&lt;br>
應該要&lt;strong>從現在這個點開始一定會比前面那個點還好&lt;/strong> ，(買進的價格較低)&lt;br>
我們可以&lt;strong>將cur重設為0(從這個點重新出發)&lt;/strong> 。&lt;/p>
&lt;p>反之如果價格比較高的話，我們可以計算現在的利潤，&lt;br>
並和全局最大值比較後再更新全局最大值。&lt;br>
所以每次依序計算現在的利潤決定是否重新選擇出發點，&lt;br>
再處理好全局最大值的紀錄即可解決此題。&lt;/p>
&lt;p>這邊Java和Python的程式碼僅差別在設定條件的方式不同而已，&lt;br>
但本質一樣是在處理&lt;strong>現有的值&lt;/strong> 及&lt;strong>最大值&lt;/strong> 這兩項。&lt;br>
讀者可以自行選用處理的方式。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/70c5a699ef074023125d11ab2e1e3499.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7feef22bb492dec05f32bc93a1d4ae39.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)，掃過整個空間一次，除cur跟res外不需其他變數。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-7-dynamic-programming-d1c3255dc266?source=your_stories_page---------------------------" target="_blank" rel="noopener"
>&lt;strong>0053. Maximum Subarray&lt;/strong> &lt;/a>2. &lt;strong>Best Time to Buy and Sell Stock系列題(XDDDDD)&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 36 Merge Sort (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/</link><pubDate>Wed, 21 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 36 Merge Sort (1)" />&lt;p>&lt;strong>0148. Sort List (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Sort a linked list in &lt;em>O&lt;/em>(&lt;em>n&lt;/em> log &lt;em>n&lt;/em>) time using constant space complexity.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 4-&amp;gt;2-&amp;gt;1-&amp;gt;3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2-&amp;gt;3-&amp;gt;4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: -1-&amp;gt;5-&amp;gt;3-&amp;gt;4-&amp;gt;0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: -1-&amp;gt;0-&amp;gt;3-&amp;gt;4-&amp;gt;5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>試以O(n log n)的時間複雜度來排序一個linked list。&lt;br>
這題其實還有設定一個constant space complexity的條件，&lt;br>
但要達成這個條件的話，要很仔細的使用迭代的方式來做merge sort才行，&lt;br>
這邊主要會講一般的遞迴解(也就是空間複雜度不會是O(1))，&lt;br>
&lt;strong>若對迭代解有興趣，可以參考&lt;/strong> &lt;a class="link" href="https://leetcode.com/problems/sort-list/discuss/172545/Java-iterative-O%281%29-space-O%28nlogn%29-time-solution" target="_blank" rel="noopener"
>&lt;strong>theoneneo&lt;/strong> &lt;/a>&lt;strong>或&lt;/strong> &lt;a class="link" href="https://leetcode.com/problems/sort-list/discuss/268268/Meeting-the-O%281%29-requirement" target="_blank" rel="noopener"
>** sladkey**&lt;/a>** 的解法。**&lt;/p>
&lt;p>關於排序有很多不同的方式，&lt;br>
我們這邊先來講一個相當常見且經典的排序法：&lt;strong>合併排序法(Merge Sort)&lt;/strong>&lt;/p>
&lt;p>合併排序法的概念是&lt;strong>先拆半再合併&lt;/strong> ，一般在演算法中為了遞迴起見，&lt;br>
會直接把拆半的部分叫&lt;strong>mergesort&lt;/strong> ，而合併的部分就稱為&lt;strong>merge&lt;/strong> 。&lt;/p>
&lt;p>什麼是&lt;strong>拆半&lt;/strong> ？就是每次將整組資料分成兩半，&lt;br>
一路拆分直到只剩下一個，這時候每一個單位而言均為排序好的狀態。&lt;br>
(廢話XD 就一個而已當然是排好的)&lt;/p>
&lt;p>拆分完以後，要進行&lt;strong>合併&lt;/strong> 的動作。&lt;br>
合併就是指將同一層的兩組資料，按大小&lt;strong>由小到大&lt;/strong> 置入。&lt;br>
我們可以參考範例的動畫，一開始由於拆到每組只剩下一個，&lt;br>
可以很輕易的比較誰大誰小，進而每次將較小的放入到合併的陣列中，&lt;br>
所以&lt;strong>每一次合併&lt;/strong> 完以後，我們都可以得到一個**由小排到大的一組資料，&lt;br>
同時下一次我們依舊可以使用兩組各自由小排到大的資料，&lt;br>
使用two pointer的方式就可以依序將其合併。**最後合併回最開始那一層，我們就可以得到一個排序好的陣列了。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-001.gif"
width="1086"
height="541"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-001_hua930a83c4d374e7aadc88830e770d7e8_432307_480x0_resize_box_1.gif 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-001_hua930a83c4d374e7aadc88830e770d7e8_432307_1024x0_resize_box_1.gif 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="200"
data-flex-basis="481px"
>&lt;/p>
&lt;p>Merge Sort範例&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-002.jpeg"
width="800"
height="422"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-002_hu1d9da78e54a9a3c21fe8d35ffdf34ac2_15075_480x0_resize_q75_box.jpeg 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-36-merge-sort-1/image-002_hu1d9da78e54a9a3c21fe8d35ffdf34ac2_15075_1024x0_resize_q75_box.jpeg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="189"
data-flex-basis="454px"
>&lt;/p>
&lt;p>最後排序完的結果&lt;/p>
&lt;p>這樣子將目標先拆小以後再進行合併的手段，&lt;br>
我們通常稱之為&lt;strong>分治法(divide-and-conquer)&lt;/strong> ，&lt;br>
也就是將大問題拆成小問題解決的一套思路。&lt;br>
由於一定要拆成每組只有單筆資料，每次拆分為一半，&lt;br>
故拆分的時候，會拆成logN層；又每次合併也都需要掃過每筆資料，&lt;br>
總時間複雜度必須再乘上N，所以最終的時間複雜度為&lt;strong>O(NlogN)&lt;/strong> 。&lt;/p>
&lt;p>當中每次合併都需求一個新的位置來作為承接它的狀態，&lt;br>
所以一般來說可使用&lt;strong>O(N)&lt;/strong> 的空間來儲存。&lt;/p>
&lt;p>總體而言，一個mergesort的演算法流程大致如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>function mergesort(arr, l, r) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if r &amp;gt; l {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> m = (l+r)/2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> mergesort(arr, l, m)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> mergesort(arr, m+1, r)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> merge(arr, l, m, r)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>function merge(arr, l, m, r) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 開一個新的陣列tmp，將arr的index l到index r的部分複製過去(包含r)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> i = l, j = m+1, cnt = 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 比較tmp[i]和tmp[j]，將較小的複製到arr[l+cnt]並遞增cnt跟有被複製的i/j其一
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 重複上一個步驟直到一方沒有可以比較的部分，將剩餘的數字全數依序放入arr中
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>回到我們的問題，&lt;br>
現在要排序的應該是LinkedList，和陣列的唯一差別是，&lt;br>
我們需要一些手段才能取到中間點，這裡同樣使用slow跟fast兩個pointer的方式，讓slow一次走一格，而fast一次走兩格，直到fast到底的時候(遇到NIL)就代表slow應該走到一半了，此時不要忘記將中間的&lt;strong>slow的前一個節點prev跟slow進行斷開&lt;/strong> ，prev的用途就是用來紀錄slow的前一個節點的。&lt;br>
(因為不是陣列，我們是依靠&lt;strong>next是否為NIL&lt;/strong> 這點來判斷節點的分組)&lt;/p>
&lt;p>接著在merge的部分，我們取用了一個n作為dummy node(也就是用來紀錄開頭用的節點)，接著使用iterator(ite)來進行檢查，同樣是檢查哪個比較小，&lt;br>
這時&lt;strong>對於Linked List而言應該是將節點串接在後面&lt;/strong> 即可。(不要忘記串接了某一個以後，該節點也要往下走，相當於陣列中的i跟j其一要遞增。)&lt;/p>
&lt;p>最後同樣，若有一方無法比較，則我們可以直接把剩下的節點接上去。&lt;br>
(ite.next = n1或ite.next = n2)&lt;br>
範例程式碼的部分這邊採用了leetcode使用者jeantimex的解法，&lt;br>
筆者加了一點註解，搭配前面文章的說明，&lt;br>
使用者應該可以較輕鬆地了解整個解題的思路和作法。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e9a0452040f4ca99287e7f96a667baa5.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/ec297770b4aece9582dcdcd5bc10005c.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(NlogN), O(logN)&lt;br>
將一個串列不斷拆成二等份，直到剩下單一節點，&lt;br>
相當於在求N可以被二分拆幾次，乘上最終會有N個單節點再次合併，&lt;br>
故總體時間複雜度為O(NlogN)。) &lt;br>
(註:這只是很粗糙的說法，有興趣可以翻閱演算法書籍，會有較嚴謹的證明)&lt;br>
(對於每一次的拆分搜尋都需要用O(1)的記憶體來儲存這層的stack，&lt;br>
理想狀況下會有logN層，故平均空間複雜度為O(logN)，&lt;br>
最差的狀況則為O(N))&lt;/p>
&lt;p>「還有一些常見的排序，你能說出它們的時間複雜度嗎？」&lt;br>
(selection/insertion/bubble等均為O(N²)，quick/merge均為O(NlogN)，&lt;br>
需留意quicksort的worst case是O(N²))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-4-6a631eb50da3?source=your_stories_page---------------------------" target="_blank" rel="noopener"
>&lt;strong>0021. Merge Two Sorted Lists (Easy)&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 35 BST (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-35-bst-3/</link><pubDate>Tue, 20 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-35-bst-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 35 BST (3)" />&lt;p>&lt;strong>0108. Convert Sorted Array to Binary Search Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array where elements are sorted in ascending order, convert it to a height balanced BST.&lt;/p>
&lt;p>For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of &lt;em>every&lt;/em> node never differs by more than 1.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given the sorted array: [-10,-3,0,5,9],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -3 9
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / /
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -10 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個陣列，其元素以&lt;strong>升冪排序&lt;/strong> (也就是後面的一定比前面大)，&lt;br>
試將其轉成一個高度平衡的二元搜尋樹。&lt;/p>
&lt;p>高度平衡的樹由於已在先前的題目中講過了(&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-20-tree-6-e08dedd83656?source=friends_link&amp;amp;sk=8b1b089b81ea49c4572d84f8103427b4" target="_blank" rel="noopener"
>0110. Balanced Binary Tree&lt;/a>)，&lt;br>
這邊就不再贅述，簡言之就是對每個節點，&lt;br>
其兩邊的子樹深度相差均&amp;lt;=1就對了！&lt;/p>
&lt;p>我們知道要達到這個條件，最基本的就是一個root的左右兩邊要公平，&lt;br>
所以最簡單的作法就是取中位數作為根，其左邊就是左子樹的所有節點，&lt;br>
右邊就是右子樹的所有節點；再分別讓各自的左右子樹再次拆分，直到分到沒有節點為止。&lt;/p>
&lt;p>這樣作可以讓每一層都均分節點，從而讓每個分支的深度基本接近一致。&lt;br>
故整體流程如下：&lt;/p>
&lt;ol>
&lt;li>檢查陣列是否是空的或者null，是的話直接回傳&lt;/li>
&lt;li>呼叫一個用來遞迴建立BST的函式，這邊命名成getNode()&lt;/li>
&lt;li>getNode會輸入陣列以及當下的左右邊界(nums, l, r) &lt;br>
(一開始l = 0, r = N-1, N是nums的總數)&lt;/li>
&lt;li>每次先檢查左右邊界是否黃金交叉(表示已經完成了，可以回傳null)&lt;/li>
&lt;li>讓mid = l加r的一半，直接建立一個root節點&lt;/li>
&lt;li>root節點的&lt;strong>左節點&lt;/strong> 就應該是呼叫&lt;strong>getNode(nums, l, mid-1)&lt;/strong> 得到的結果&lt;/li>
&lt;li>root節點的&lt;strong>右節點&lt;/strong> 則會是&lt;strong>getNode(nums, mid+1, r)&lt;/strong> 得到的結果&lt;/li>
&lt;li>回傳root&lt;/li>
&lt;/ol>
&lt;p>我們可以看到每次會抓中間值產生一個節點，再利用已排序的特性，&lt;br>
繼續進入遞迴往下將左邊和右邊的節點處理完畢。&lt;br>
思考它的執行流程，應該會發現總體而言我們會先一路來到最左邊的節點，&lt;br>
再回頭建立每個遞迴函式的右邊節點；&lt;br>
也就是說，程式執行的優先順序是&lt;strong>先往深處的方向走&lt;/strong> 而非先將這一層的狀況處理完，這種模式我們稱之為&lt;strong>深度優先搜尋(Depth-First Search, DFS)&lt;/strong> ；&lt;br>
如果換作是優先順序是&lt;strong>先廣泛地處理完這一層，再往下一層走&lt;/strong> ，這種模式就稱之為&lt;strong>廣度優先搜尋(Breadth-First Search, BFS)&lt;/strong> 。&lt;/p>
&lt;p>程式碼的部分，僅需留意Java因為想避免overflow的狀況，&lt;br>
計算的方式為 &lt;strong>start + (end - start) / 2&lt;/strong> ，而非(start + end) / 2。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e2c3d6cc2abcaafed409efcbdcd2be63.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/595347ffa074df96a6a00bd276ae19ec.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)&lt;br>
每個節點都會掃過一遍，且基本和其他節點沒有太多連帶關係。)&lt;/p>
&lt;p>「那麼如果要將一個BST轉成&lt;strong>排序陣列&lt;/strong> 呢？」&lt;br>
(原則上可用&lt;strong>Inorder Traversal&lt;/strong> ，&lt;br>
但留意不加NIL的狀況其實中間樹的架構資訊可能會就此流失掉)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol>
&lt;li>&lt;a class="link" href="https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/" target="_blank" rel="noopener"
>&lt;strong>0109. Convert Sorted List to Binary Search Tree&lt;/strong> &lt;/a>&lt;strong>(起始給的從陣列/串列改成排序好的LinkedList)&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 34 Array (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-34-array-6/</link><pubDate>Mon, 19 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-34-array-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 34 Array (6)" />&lt;p>&lt;strong>0977. Squares of a Sorted Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of integers &lt;code>A&lt;/code> sorted in non-decreasing order, return an array of the squares of each number, also in sorted non-decreasing order.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [-4,-1,0,3,10]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [0,1,9,16,100]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [-7,-3,2,3,11]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [4,9,9,49,121]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>1 &amp;lt;= A.length &amp;lt;= 10000&lt;/code>&lt;/li>
&lt;li>&lt;code>-10000 &amp;lt;= A[i] &amp;lt;= 10000&lt;/code>&lt;/li>
&lt;li>&lt;code>A&lt;/code> is sorted in non-decreasing order.&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個非遞減排序(也就是相等或遞增)的陣列，&lt;br>
以排序好的狀況回傳其每個元素平方後所得的陣列。&lt;/p>
&lt;p>一般我們所熟知的排序應該需要至少O(NlogN)的狀況才能達成，&lt;br>
(之後筆者會再挑一題來專門作排序這個部分的問題)&lt;br>
但這題在平方過以後，並不算完全散亂的狀態，&lt;br>
原先&lt;strong>負整數的部分平方後會由大到小排列&lt;/strong> ；&lt;br>
原先&lt;strong>0到正整數的部分平方後則會由小到大排列&lt;/strong> 。&lt;br>
利用這點我們可以使用two pointer的模式來進行處理，&lt;br>
每次將兩邊的元素絕對值進行比較，比較大的代表其平方後比較大，&lt;br>
將其取出置於新的陣列/串列的最右邊，依序往回填。&lt;/p>
&lt;p>實作上，如果不限制A必須保持原樣的話，&lt;br>
也可以先將負號的部分全數去掉，再進行後面的比較時，&lt;br>
就可免去取絕對值了。&lt;/p>
&lt;p>Java的部分兩個方法皆有提供，讀者可依實際狀況決定寫法。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/37366814ed0061020dd40565400afd5c.js">&lt;/script>
&lt;p>Python的部分，還另外提供了一個偷吃步的方法：&lt;br>
使用sorted函式搭配list comprehension，一行即可解決問題，&lt;br>
但其時間複雜度為O(NlogN) (因為直接使用排序法)&lt;/p>
&lt;p>&lt;em>神奇的是，這個方法還比較快XD&lt;/em>&lt;br>
(估計是A的長度限制在比較小的範圍，可能測試資料也不是很大，&lt;br>
所以主動用排序帶來的負面效益較低的原因)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/1a81a05cc447417389bb832aab159685.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)&lt;br>
每個陣列均會掃過一次，且會產生一個新的陣列。)&lt;/p>
&lt;p>「這題在產生新的陣列的時候跟合併排序(Merge Sort)其實很像，&lt;br>
可以概略描述Merge Sort的作法嗎？」&lt;br>
(可以XD 這個我們之後會專門寫一題講解)&lt;br>
(如果不想等的話，可以先查詢Merge Sort，應該有蠻多資料的，&lt;br>
但簡言之，就是每次將陣列拆兩半，&lt;br>
分別各自排序過後(mergesort)，再依序合併起來(merge)。)&lt;/p>
&lt;p>&lt;strong>相似及延伸：&lt;br>
1.&lt;/strong> &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-4-6a631eb50da3?source=your_stories_page---------------------------" target="_blank" rel="noopener"
>0021. Merge Two Sorted Lists (Easy)&lt;/a>&lt;br>
2. &lt;a class="link" href="https://leetcode.com/problems/sort-list/" target="_blank" rel="noopener"
>0148. Sort List (Medium)&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 33 Array (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-33-array-5/</link><pubDate>Sun, 18 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-33-array-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 33 Array (5)" />&lt;p>&lt;strong>0905. Sort Array By Parity (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array &lt;code>A&lt;/code> of non-negative integers, return an array consisting of all the even elements of &lt;code>A&lt;/code>, followed by all the odd elements of &lt;code>A&lt;/code>.&lt;/p>
&lt;p>You may return any answer array that satisfies this condition.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [3,1,2,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [2,4,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>The outputs [4,2,3,1], [2,4,1,3], and [4,2,1,3] would also be accepted.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>1 &amp;lt;= A.length &amp;lt;= 5000&lt;/code>&lt;/li>
&lt;li>&lt;code>0 &amp;lt;= A[i] &amp;lt;= 5000&lt;/code>&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個不含負整數的整數陣列A，回傳一個陣列，&lt;br>
這個陣列的前面會是所有A的偶數的元素，&lt;br>
跟在後面的是所有A的奇數的元素的部分。&lt;/p>
&lt;p>這題我們在先前的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-25-array-3-bca3bca74ca2?source=friends_link&amp;amp;sk=2b26f2e316bbfd7bc96ff372259e652a" target="_blank" rel="noopener"
>Move Zeros&lt;/a>題目中有提到過類似的部分，&lt;br>
如果當時我們只想把0往後挪而不需考慮保留原順序，&lt;br>
可以從兩端開始掃描，&lt;strong>找到左邊是0而右邊非0並交換&lt;/strong> 就可以解完此題；&lt;br>
這題概念是一樣的，只是變成要&lt;strong>左邊全是偶數，右邊全是奇數&lt;/strong> 。&lt;br>
演算的順序大概會像這樣：&lt;/p>
&lt;ol>
&lt;li>分別取兩端的index作為起始(i = 0, j = l-1, l為A的長度)&lt;/li>
&lt;li>先確認i的位置是否為奇數，若否，則遞增i，直到A[i]為奇數&lt;/li>
&lt;li>再確認j的位置是否為偶數，若否，則遞減j，直到A[j]為偶數&lt;/li>
&lt;li>交換A[i], A[j]&lt;/li>
&lt;li>重複前述2~4的操作直到i不再小於j(開始前也要檢查)&lt;/li>
&lt;li>此時全數交換完畢，所有偶數應排在奇數之前&lt;/li>
&lt;/ol>
&lt;p>這邊程式碼需要注意continue的作用，&lt;br>
目的是讓每次index變動都進行i&amp;lt;j的檢查，&lt;br>
唯有這個條件成立，我們才有可能需要進行交換。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/8f6aee4e11e4bd4a225c1efbe622f17f.js">&lt;/script>
&lt;p>Python的部分後面提供了一個非in-place的作法，&lt;br>
也就是各自將偶數和奇數的串列累積起來，&lt;br>
最後再將其連接。好處是比較簡單，缺點是要額外的空間來存，&lt;br>
端看使用者需求和題目需求來決定。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7de1ffdc528c5ff7ce72ad3e0b4fea78.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)&lt;br>
two pointer會掃過整個陣列，所以時間複雜度為O(N)；&lt;br>
如果不另外開陣列/串列的話，可以用in-place達到則空間複雜度為O(1)，&lt;br>
如果像Python額外提到的方法的話則由於額外儲存的關係需要O(N))&lt;/p>
&lt;p>「如果除了偶數在前，奇數在後以外，要按照原先順序排列呢？」&lt;br>
(Python的另一個解就會按順序排)&lt;/p>
&lt;p>&lt;strong>相似及延伸：&lt;br>
1.&lt;/strong> &lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-25-array-3-bca3bca74ca2?source=friends_link&amp;amp;sk=2b26f2e316bbfd7bc96ff372259e652a" target="_blank" rel="noopener"
>** 0283**. Move Zeros&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 32 BST (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-32-bst-2/</link><pubDate>Fri, 16 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-32-bst-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 32 BST (2)" />&lt;p>&lt;strong>0700. Search in a Binary Search Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST that the node’s value equals the given value. Return the subtree rooted with that node. If such node doesn’t exist, you should return NULL.&lt;/p>
&lt;p>For example,&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given the tree:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 7
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>And the value to search: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>You should return this subtree:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In the example above, if we want to search the value &lt;code>5&lt;/code>, since there is no node with value &lt;code>5&lt;/code>, we should return &lt;code>NULL&lt;/code>.&lt;/p>
&lt;p>Note that an empty tree is represented by &lt;code>NULL&lt;/code>, therefore you would see the expected output (serialized tree format) as &lt;code>[]&lt;/code>, not &lt;code>null&lt;/code>.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元搜尋樹及一個值，試找到這個樹上含有該值的節點；&lt;br>
如果找不到任何節點的值和此值相等的話，回傳NULL。&lt;/p>
&lt;p>一個Binary Search Tree在進行搜尋特定值上最大的好處就是，&lt;br>
**碰到相等是目標，比完較小往左走，&lt;br>
比完較大往右走，走到盡頭就沒有。(XDDDD)**類似binary search，只是我們的每次切半/改動上下界的操作，&lt;br>
更改為往左走或往右走。&lt;/p>
&lt;p>所以我們只要進行遞迴，直到走到NULL(NIL)或走到剛好對的值即可，&lt;br>
下面的程式碼中，由於判斷&lt;strong>root是否為NIL&lt;/strong> 及&lt;strong>root的值等於目標值&lt;/strong> 的狀況，&lt;br>
均為&lt;strong>回傳root&lt;/strong> (雖然一種情況是NIL，另一種情況不是)，&lt;br>
所以我們可以將之合併。&lt;/p>
&lt;p>而當&lt;strong>val &amp;lt; root.val&lt;/strong> 的時候，&lt;br>
選擇&lt;strong>往左走&lt;/strong> 去找比當下的root&lt;strong>更小的值&lt;/strong> 來比較，反之則往右走。&lt;/p>
&lt;p>在實測上以筆者目前的觀察，是否全數使用if/elif連貫的判斷式，&lt;br>
或者前面root的回傳是否合併成一個情況，&lt;br>
均&lt;strong>對執行的速度沒有特別明顯的影響&lt;/strong> ，&lt;br>
故讀者可依自己的喜好選擇撰寫的方式，只需邏輯正確即可。&lt;/p>
&lt;p>此外，之前可能有提到過的&lt;strong>三元運算子&lt;/strong> ( ? : )也僅是方便縮短行數，&lt;br>
同樣對結果沒有影響。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0e78b4ea04bb300bf519848a8bd0121f.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c3a2e316115c9a128256dfd3a76a1b5c.js">&lt;/script>
&lt;p>如果讀者習慣於使用LeetCode解二元樹或二元搜尋樹的題目，&lt;br>
應該會發現其實&lt;strong>二元搜尋樹是可以使用陣列/串列的方式進行輸入&lt;/strong> 的。&lt;br>
這麼做的好處是只要管理好index，就可以用&lt;strong>index的操作&lt;/strong> 來達到走訪某個節點的目的，而不用真的去把每個節點都進行連結到left/right。&lt;br>
缺點的部分則是有些地方必須輸入null進去(因為有可能會是null節點)。&lt;/p>
&lt;p>讀者可以找一些題目來思考一下，&lt;br>
(像是前面的&lt;a class="link" href="https://leetcode.com/problems/binary-tree-inorder-traversal/" target="_blank" rel="noopener"
>0094. Binary Tree Inorder Traversal&lt;/a>)&lt;br>
如果從index i想要走到其left/right節點，這兩個的節點index會是多少呢？&lt;br>
讀者可以開啟Testcase中的Tree Visualizer，&lt;br>
來觀看輸入的陣列會長成的樹的形狀。&lt;br>
(註：這種表示法未必是通用的，但可以做為參考。)&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(&lt;strong>Worst case O(N)/Average Case O(logN)&lt;/strong> , O(1)，&lt;br>
最糟的狀況是所有節點集中在同一側，一路搜尋到最底下；&lt;br>
平均來說，如果節點較接近平衡的分布的話，&lt;br>
每次搜尋往下走能去掉一半的可能性，所以會是O(logN)。&lt;br>
由於不需要額外的紀錄，所以空間複雜度為O(1))&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/insert-into-a-binary-search-tree/" target="_blank" rel="noopener"
>&lt;strong>0701. Insert into a Binary Search Tree&lt;/strong> &lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;/strong> 感謝&lt;strong>Tony Kuo&lt;/strong> 的建議，這邊附上之前講的BST定義及validation的文章。&lt;br>
&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"
>&lt;strong>從LeetCode學演算法 — 16 BST (1)&lt;/strong> &lt;/a> &lt;strong>(0098. Validate Binary Search Tree)&lt;/strong>&lt;/p>
&lt;p>&lt;strong>(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 31 Linked List (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/</link><pubDate>Thu, 15 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 31 Linked List (4)" />&lt;p>&lt;strong>0141. Linked List Cycle (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a linked list, determine if it has a cycle in it.&lt;/p>
&lt;p>To represent a cycle in the given linked list, we use an integer &lt;code>pos&lt;/code> which represents the position (0-indexed) in the linked list where tail connects to. If &lt;code>pos&lt;/code> is &lt;code>-1&lt;/code>, then there is no cycle in the linked list.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: head = [3,2,0,-4], pos = 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There is a cycle in the linked list, where tail connects to the second node.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-001.png"
width="531"
height="171"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-001_huc8b5ea95bee93cfe24c6de8f026c2b3c_9592_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-001_huc8b5ea95bee93cfe24c6de8f026c2b3c_9592_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="310"
data-flex-basis="745px"
>&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: head = [1,2], pos = 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There is a cycle in the linked list, where tail connects to the first node.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-002.png"
width="201"
height="105"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-002_hu2ba821ed629aefdc155ed7955ffc7473_4120_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-002_hu2ba821ed629aefdc155ed7955ffc7473_4120_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="191"
data-flex-basis="459px"
>&lt;/p>
&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: head = [1], pos = -1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There is no cycle in the linked list.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-003.png"
width="65"
height="65"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-003_hu9b6f26b409de18d69f860a880c63c793_1790_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-31-linked-list-4/image-003_hu9b6f26b409de18d69f860a880c63c793_1790_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;/p>
&lt;p>Can you solve it using &lt;em>O(1)&lt;/em> (i.e. constant) memory?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個Linked List，試檢查其是否含有一個&lt;strong>環(Cycle)&lt;/strong> 在裡面。&lt;br>
我們有一小段時間沒有講Linked List，這邊不再贅述其基礎特性，&lt;br>
想要複習的讀者可以參閱&lt;a class="link" href="../learn-algorithm-from-leetcode-4-linked-list-1" >第4篇&lt;/a>的說明。&lt;/p>
&lt;p>當我們在考慮這個題目的時候，會留意到兩個特性：&lt;/p>
&lt;ol>
&lt;li>這個Linked List是指Single Linked List(也就是指向的方向只有單向)。&lt;/li>
&lt;li>如果有環的話，應該會從最後一個節點再連接到前面的節點。&lt;br>
(從中間的話就會產生分歧的狀況)&lt;/li>
&lt;/ol>
&lt;p>在以上的特性狀況下，假設有一個環在Linked List中的話，&lt;br>
取一個節點從head開始不斷往其next走，會先經過最後一個節點，&lt;br>
接著再接回到前面某個節點再往下走，這樣會是一個循環；&lt;br>
更重要的是，顯然&lt;strong>一進入這個環中，接下來就會一直在環內移動&lt;/strong> 。&lt;br>
(因為走到尾端又會再接回來)&lt;/p>
&lt;p>這裡我們引入一個蠻常用的解題方式：&lt;strong>設定快速和慢速的指標&lt;/strong> 。&lt;br>
我們讓fast和slow先設定在head的位置，每次&lt;strong>fast走兩步，slow走一步&lt;/strong> ，&lt;br>
它們就像是國小時針分針追趕的感覺一樣。&lt;/p>
&lt;p>接下來我們可以將狀況分成以下兩種：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>假設&lt;strong>有環&lt;/strong> 的狀況，&lt;br>
&lt;strong>不管走多快多慢都會陷入這個環內&lt;/strong> ，&lt;br>
所以會變成&lt;strong>每次fast多走了一步，這一步用來追趕slow&lt;/strong> 。&lt;br>
因為slow也沒別的地方可以躲，所以fast每次多走一步一定可以趕得上&lt;br>
(也因為一步一步趕所以沒有追上卻錯開的可能)。&lt;br>
因此，我們知道fast和slow最終會來到相同的位置(也就是&lt;strong>兩者相等&lt;/strong> )&lt;/p>
&lt;/li>
&lt;li>
&lt;p>假設&lt;strong>沒有環&lt;/strong> 的狀況，&lt;br>
由於不會重複，故最終&lt;strong>fast一定會先走到尾端&lt;/strong> ，最後看到&lt;strong>NIL&lt;/strong> 。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>故我們要做的事情很簡單，只要先設定fast跟slow，&lt;br>
在它們沒有走到NIL之前，每次去檢查fast是否有追上slow。&lt;br>
追上的話就回傳&lt;strong>true&lt;/strong> ，而&lt;strong>如果看到fast的下一個節點是NIL&lt;/strong> 的話，&lt;br>
就代表&lt;strong>走到盡頭了&lt;/strong> ，此時應該要回傳&lt;strong>false&lt;/strong> 。&lt;/p>
&lt;p>整個演算的順序：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>考量起始的狀況，我們必須先檢查&lt;strong>head跟head.next&lt;/strong> 當中是否有NIL值&lt;/p>
&lt;/li>
&lt;li>
&lt;p>開始一個迴圈，&lt;br>
開始前讓&lt;strong>fast被設定為fast.next.next，slow則被設定為slow.next&lt;/strong> 。&lt;br>
當fast還沒有遇到NIL前，每次各自走相應步數，再檢查兩者是否相等。&lt;br>
(&lt;strong>相等表示有環&lt;/strong> ，回傳&lt;strong>true&lt;/strong> )&lt;br>
請注意：當&lt;strong>fast和fast.next&lt;/strong> 都處於&lt;strong>非NIL&lt;/strong> 的狀況時，迴圈才能夠執行。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>當fast或fast.next是NIL的話：表示走到盡頭了！跳離迴圈後，&lt;br>
將其&lt;strong>return false&lt;/strong> 以表示它當中並沒有環。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>寫成程式碼大概如下面所示：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7d39c65d06367e19a2bd961a82aae5cd.js">&lt;/script>
&lt;p>Python這邊額外提供了LeetCode使用者 &lt;em>StefanPochmann&lt;/em> 的做法，&lt;br>
這個做法使用了try…except來進行錯誤處理，&lt;br>
有興趣的讀者不妨試試看。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/11c7a3a81a54be093a070b2d046f8346.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)&lt;br>
由於fast比slow每次多走一步，我們可預期在走環的部分時，為了相遇走的長度的複雜度為O(K)。那麼K最大也頂多就是囊括所有節點，&lt;br>
所以&lt;strong>時間的複雜度最大就會取決於N&lt;/strong> 。&lt;br>
當然，還有另一種狀況是&lt;strong>裡面沒有環&lt;/strong> ，&lt;br>
時間複雜度也是O(N)。(走到底就結束了)&lt;br>
另外，我們沒有另外需要存下其他整個LinkedList的節點，所以僅有一些必要的節點被宣告，故空間複雜度為O(1))&lt;/p>
&lt;p>&lt;strong>相似及延伸：&lt;br>
1.&lt;/strong> &lt;a class="link" href="https://leetcode.com/problems/linked-list-cycle-ii/" target="_blank" rel="noopener"
>** 0142.** Linked List Cycle II&lt;/a>&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 30 Tree (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-30-tree-7/</link><pubDate>Wed, 14 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-30-tree-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 30 Tree (7)" />&lt;p>&lt;strong>0144. Binary Tree Preorder Traversal (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, return the &lt;em>preorder&lt;/em> traversal of its nodes’ values.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,null,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: [1,2,3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up:&lt;/strong> Recursive solution is trivial, could you do it iteratively?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，試求其Preorder Traversal(前序走訪)。&lt;/p>
&lt;p>先前我們介紹過&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"
>Inorder Traversal&lt;/a>，對於Preorder，大家應該也會有一個心理準備，就是使用遞迴會很簡單，迭代則會不容易思考XD。&lt;br>
再複習一下，所謂的Preorder指的是走訪的順序依序為&lt;strong>根-&amp;gt;左-&amp;gt;右&lt;/strong> ，走訪的時候遇到根的時後先輸出，接著優先往左邊走，當左邊的全走完時，&lt;br>
才檢查右邊的節點，依此順序將所有節點輸出。&lt;/p>
&lt;p>作為遞迴的方式，我們每次將根節點的值放進res(result)中，接著再呼叫遞迴依序進行左邊節點和右邊節點的走訪即可。&lt;br>
Java中使用add，Python中則用append，在前面不要忘記檢查當走到NIL(null/None)的時候要退回到上一層(直接return)。&lt;/p>
&lt;p>那麼，迭代的方式呢？&lt;br>
由於之前我們已經提到過在Python裡面，List的append/pop可以拿來當作stack的push跟pop來使用，要用Queue的話則必須用Deque。&lt;br>
所以我們這邊依舊使用stack的思路來解題。&lt;/p>
&lt;p>我們已經知道對於stack來說有&lt;strong>LIFO(後進先出)&lt;/strong> 的特性，&lt;br>
利用這點，我們可以讓進入stack的順序設定為右-&amp;gt;左-&amp;gt;根，&lt;br>
如此pop出來的時候順序即會符合根-&amp;gt;左-&amp;gt;右的狀態。&lt;/p>
&lt;p>思路如下：(前面應先檢查root是否為NIL)&lt;/p>
&lt;ol>
&lt;li>設置一個stack名為st，將root放入，再設一個記錄結果的串列res。&lt;/li>
&lt;li>當st裡面有節點時，&lt;strong>pop出一個節點n&lt;/strong> 。&lt;/li>
&lt;li>將&lt;strong>n的右節點&lt;/strong> push至st(如該節點不為NIL)&lt;/li>
&lt;li>將&lt;strong>n的左節點&lt;/strong> push至st(如該節點不為NIL)&lt;/li>
&lt;li>將&lt;strong>n的值&lt;/strong> 放到res中&lt;/li>
&lt;li>重複2~5&lt;strong>直到st中沒有任何節點&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>這樣一來，我們可以使用一個迴圈，令res依preorder的順序拿到節點值。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/d5573c268e29f803c7e47908a964bc61.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4b87a227dbf05ef4cf8ae77011422571.js">&lt;/script>
&lt;p>這題比較困難的部分就在於迭代法的解法，&lt;br>
如果讀者一時無法理解，請嘗試用紙筆列出一些狀況操作，&lt;br>
會較能夠體會該方法是如何利用迴圈來達到目標的。&lt;/p>
&lt;p>同時，&lt;strong>存入根節點的值的時間點不同&lt;/strong> ，&lt;br>
基本就決定了它是哪一種Traversal。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)，因為最終都需要儲存整份樹攤平的結果)&lt;/p>
&lt;p>「樹的形狀會影響其時間空間複雜度嗎？」&lt;br>
(只會影響中間空間暫存需要的大小(因為有stack或call stack)，&lt;br>
但&lt;strong>複雜度不變&lt;/strong> )&lt;/p>
&lt;p>「給定一棵二元樹，&lt;br>
請依序寫出preorder/inorder/postorder/levelorder的結果」&lt;br>
(簡單卻重要，請讀者務必自己畫一棵並嘗試寫一下順序，&lt;br>
看看是否有搞混的地方，尤其是每次印出根節點的時機很重要。)&lt;/p>
&lt;p>「如果該樹是BST，且改為inorder的話，&lt;br>
能否找到任二節點相差的絕對值當中的最小值？」&lt;br>
(利用inorder的狀態排出來的順序會是遞增排列，每次檢查相鄰的數即可。)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol>
&lt;li>&lt;a class="link" href="https://leetcode.com/problems/binary-tree-postorder-traversal" target="_blank" rel="noopener"
>&lt;strong>0145. Binary Tree Postorder Traversal&lt;/strong> &lt;/a>&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 29 Dynamic Programming (7)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-29-dynamic-programming-7/</link><pubDate>Mon, 12 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-29-dynamic-programming-7/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 29 Dynamic Programming (7)" />&lt;p>&lt;strong>0213. House Robber II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are &lt;strong>arranged in a circle.&lt;/strong> That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and ** it will automatically contact the police if two adjacent houses were broken into on the same night**.&lt;/p>
&lt;p>Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight &lt;strong>without alerting the police&lt;/strong> .&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,3,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>You cannot rob house 1 (money = 2) and then rob house 3 (money = 2),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>because they are adjacent houses.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Rob house 1 (money = 1) and then rob house 3 (money = 3).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Total amount you can rob = 1 + 3 = 4.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>繼上一次&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-28-dynamic-programming-6-8e5a81a8437d?source=friends_link&amp;amp;sk=d87bd13d5e6a85da75c83222cddc0d60" target="_blank" rel="noopener"
>&lt;strong>偷完一排房子&lt;/strong> &lt;/a>以後，我們決定挑戰更高難度的偷竊XD&lt;br>
(有完沒完啦！)&lt;/p>
&lt;p>保全狀態依舊是相鄰房子連續被偷就會響警報，不同的是，&lt;br>
現在房子的分布是圓形！也就是第一間和最後一間是相鄰的，&lt;br>
這就會造成我們上一次使用的算法會出現問題。&lt;/p>
&lt;p>那麼怎麼辦呢？&lt;br>
第一間和最後一間有關聯是不是？&lt;br>
那我們就來斷開魂結，斷開鎖鏈，斷開一切的牽連吧！(大誤)&lt;/p>
&lt;p>這裡我們為求方便起見，使用0為index開頭來描述，&lt;br>
這樣等一下對照程式碼也比較方便。&lt;br>
我們令nums的總長度為&lt;strong>l&lt;/strong> ，&lt;br>
並且使用&lt;strong>dp[i]&lt;/strong> 來表示偷到index i的房子時當前所能得到的最大金額。&lt;/p>
&lt;p>如何處理index 0跟l-1的關係呢？&lt;br>
針對index 0的話，只會分成&lt;strong>偷&lt;/strong> 或&lt;strong>不偷&lt;/strong> 。&lt;/p>
&lt;p>古語有云：&lt;/p>
&lt;blockquote>
&lt;p>To rob, or not to rob, that is a question.&lt;/p>
&lt;ul>
&lt;li>莎士比亞沒有說過&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>所以我們可以分開來討論。&lt;br>
假設今天無論如何&lt;strong>就是要偷index 0&lt;/strong> 的房子的話，&lt;br>
可以得到以下推論：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>index l-1不能偷&lt;/strong>&lt;/li>
&lt;li>&lt;strong>dp[0] = nums[0], dp[1] = nums[0]&lt;/strong> (偷了0就不能偷1)&lt;/li>
&lt;li>這狀況能得到的最大金額應為&lt;strong>dp[l-2]&lt;/strong> (因l-1不能偷)&lt;br>
這個狀況，我們可以給定2的起始條件並計算到dp[l-2]即可得到最大金額。&lt;/li>
&lt;/ol>
&lt;p>假設今天就是不偷index 0的房子的話，&lt;br>
可以得到以下推論：&lt;/p>
&lt;ol>
&lt;li>index l-1能不能偷只需要&lt;strong>看index l-2&lt;/strong> 決定要不要偷&lt;/li>
&lt;li>&lt;strong>dp[0] = 0, dp[1] = nums[1]&lt;/strong> (因0不偷，dp[1]要選擇偷index 1)&lt;/li>
&lt;li>這狀況能得到的最大金額應為&lt;strong>dp[l-1]&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>所以依照這兩個狀況拆開來分別計算一次，&lt;br>
將兩個結果比較大小，取較大的即為答案。&lt;/p>
&lt;p>同上一題描述的一樣，&lt;br>
我們可以利用兩個變數及一個暫存變數，來達到dp的效果。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/84b86e3506369af57e23eaa3deda9aaa.js">&lt;/script>
&lt;p>Python的部分則再額外提供了將迴圈部分包裝成函式的程式碼，&lt;br>
但實測上由於需要呼叫的原因，看起來平均會略慢於未包裝的狀況。&lt;br>
(附在底下註解處，使用者可再多執行幾次試試看)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/cb5a5b74a7ffcb35e9b704c24cbf27ee.js">&lt;/script>
&lt;p>所以總體而言，這題的根本在於，當發現有些狀態是互相關聯時，&lt;br>
&lt;strong>嘗試將其進行拆解，從而重新得到線性可計算動態規劃的狀態。&lt;/strong> 再次強調， &lt;strong>DP的精髓在於找到初始狀態，&lt;br>
及找到從一個狀態推展到下一個狀態的方法。&lt;strong>用骨牌來比喻的話，後者相當於&lt;/strong> 骨牌之間的關係&lt;/strong>，&lt;br>
前者則相當於那個&lt;strong>第一個倒下來的骨牌&lt;/strong> 。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)&lt;br>
這次的範例程式碼已經不用dp陣列來記錄了，&lt;br>
即便需要掃過nums兩次，但時間複雜度還是O(N))&lt;/p>
&lt;p>「如果保安增強，變成只要連續三棟房子內任二棟被偷即會有警報的話？」&lt;br>
(可以嘗試用類似的方式來推導)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol>
&lt;li>&lt;a class="link" href="https://leetcode.com/problems/house-robber-iii/" target="_blank" rel="noopener"
>&lt;strong>0337. House Robber III&lt;/strong> &lt;/a>2.&lt;a class="link" href="https://leetcode.com/problems/min-cost-climbing-stairs/" target="_blank" rel="noopener"
>&lt;strong>0746. Min Cost Climbing Stairs&lt;/strong> &lt;/a>&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 28 Dynamic Programming (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-28-dynamic-programming-6/</link><pubDate>Sat, 10 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-28-dynamic-programming-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 28 Dynamic Programming (6)" />&lt;p>&lt;strong>0198. House Robber (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and &lt;strong>it will automatically contact the police if two adjacent houses were broken into on the same night&lt;/strong> .&lt;/p>
&lt;p>Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight &lt;strong>without alerting the police&lt;/strong> .&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Rob house 1 (money = 1) and then rob house 3 (money = 3).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Total amount you can rob = 1 + 3 = 4.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,7,9,3,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 12
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Total amount you can rob = 2 + 9 + 1 = 12.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目描述你是一個專業的強盜，即將進行入室行竊的勾當。&lt;br>
每間房子都存有確定數量的金錢，但唯一的限制是，每間房都有安保設置，只要相鄰的二間房子在同一個晚上被闖入的話，系統就會自動報警。&lt;br>
給定一個用來表示每間房子存放金額的陣列，試求在不驚動警察狀況下，&lt;br>
最大可以獲得的金額。&lt;/p>
&lt;p>看到這個問題的時候，首先就想OS: 一間就報警的話不是最乾脆XD&lt;/p>
&lt;p>好吧，我們假設這個安保真的是有這種漏洞的話，&lt;br>
那麼怎麼偷最好呢？&lt;/p>
&lt;p>由於題目條件的限制，我們先假設一路偷到第i間，&lt;br>
所能獲得的最大金額為rob[i]，rob[i]會受到什麼限制呢？&lt;br>
假設我們走到第i間，&lt;br>
&lt;strong>選擇要偷第i間的話，意味著我們前面不能偷第i-1間&lt;/strong> 。&lt;br>
這種狀況下，我們可以將rob[i]的值拆開來算：&lt;br>
&lt;strong>rob[i] = rob[i-2] + num[i]&lt;/strong>&lt;br>
(選擇不動第i-1間，並偷了第i間，&lt;br>
而在此之前i-2間所能偷到的最大值是rob[i-2])&lt;/p>
&lt;p>那麼，選擇不偷第i間的話，意味著&lt;strong>rob[i] = rob[i-1]&lt;/strong> (因為你沒偷嘛XD)&lt;/p>
&lt;p>既然有這兩種可能，那麼我們就該選當中比較大的，&lt;br>
所以&lt;strong>rob[i] = max(rob[i-1], rob[i-2] + nums[i])&lt;/strong> 。&lt;/p>
&lt;p>讓我們考慮一下最前面的狀況：&lt;br>
rob[0] = nums[0] (第一間不用考慮前面的影響)&lt;br>
rob[1] = max(nums[0], nums[1]) (兩間選一間偷)&lt;/p>
&lt;p>所以接下來我們只需要一路用前面的式子，迴圈從i=2計算到i=n-1，&lt;br>
最後將rob[n-1]回傳即可。&lt;/p>
&lt;p>所以一路下來，讀者會發現有關動態規劃的題目，&lt;br>
一直在做的事情其實就是嘗試&lt;strong>尋找在第n項的解，&lt;br>
和前面的項次之間的關係&lt;/strong>，一旦能找到這個關係，&lt;br>
並能確認初始的條件，就能一路從頭開始計算將其解出。&lt;/p>
&lt;p>在程式碼的部分，我們可以先行考慮nums為空跟長度為1的狀況，&lt;br>
直接回傳結果以節省空間。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/b954ab22d85b03f0902bf18386d04940.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/d83c7c68910e5e456a511e45fa32f743.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(N)，掃過一次nums陣列，&lt;br>
並且也用相同長度來儲存最大的偷取金額)&lt;/p>
&lt;p>「空間複雜度可以降低嗎？」&lt;br>
(可以！可以觀察出每個rob的值之間的關聯只有和前2個值有關(i-2和i-1)&lt;br>
我們可以使用robprev, robnext搭配一個temp值，&lt;br>
在迴圈中使用類似下面的方式，可以反復更新值，如此一來，&lt;br>
就只需要O(1)的空間就可以解決此題。)&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>int tmp = robprev;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>robprev = robnext;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>robnext = Math.max(robprev, tmp + nums[i]);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;p>1.&lt;a class="link" href="https://leetcode.com/problems/house-robber-ii/" target="_blank" rel="noopener"
>&lt;strong>0213. House Robber II (Medium)&lt;/strong> &lt;/a> &lt;strong>(從線性變圓形)&lt;/strong> 2. &lt;a class="link" href="https://leetcode.com/problems/house-robber-iii/" target="_blank" rel="noopener"
>&lt;strong>0337. House Robber III (Medium)&lt;/strong> &lt;/a> (&lt;strong>變成二元樹&lt;/strong> )&lt;br>
(到底哪個鄉鎮會這樣子蓋房子啦XD)&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;/strong>&lt;/p>
&lt;p>&lt;strong>From Medium:&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Raiy Kuo - 更正Python程式碼尾端，應回傳rob[-1]或rob[l-1]即可。&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 27 Array (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-27-array-4/</link><pubDate>Fri, 09 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-27-array-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 27 Array (4)" />&lt;p>&lt;strong>0189. Rotate Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array, rotate the array to the right by &lt;em>k&lt;/em> steps, where &lt;em>k&lt;/em> is non-negative.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3,4,5,6,7] and k = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [5,6,7,1,2,3,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rotate 1 steps to the right: [7,1,2,3,4,5,6]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rotate 2 steps to the right: [6,7,1,2,3,4,5]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rotate 3 steps to the right: [5,6,7,1,2,3,4]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [-1,-100,3,99] and k = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [3,99,-1,-100]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rotate 1 steps to the right: [99,-1,-100,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rotate 2 steps to the right: [3,99,-1,-100]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Try to come up with as many solutions as you can, there are at least 3 different ways to solve this problem.&lt;/li>
&lt;li>Could you do it in-place with O(1) extra space?&lt;/li>
&lt;/ul>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個陣列，將其往右輪轉k步，&lt;br>
要求直接將該陣列調整成輪轉後的結果。&lt;/p>
&lt;p>這題一旦沒有Note的要求的話瞬間&lt;strong>簡單一百倍&lt;/strong> 。&lt;br>
舉例來說，我們可以直接將後k項和前l-k項合併起來(l為陣列長度)，&lt;br>
就會是答案了；或者，將整個陣列重複銜接一次，取[(l-k):(2*l-k)]亦可。&lt;br>
(這兩個解法筆者列在Python的註解中供讀者參閱)&lt;br>
但，它們都不是in-place。&lt;/p>
&lt;p>要考慮到in-place的話，我們必須知道，&lt;br>
一定有方法能讓他們跑到該有的地方，且不需用到超過O(1)以外的空間，&lt;br>
一般就意味著會在陣列進行swap的操作(交換兩個元素)。&lt;/p>
&lt;p>先看一下原本的例子：&lt;br>
&lt;code>[1,2,3,4,5,6,7]&lt;/code> and &lt;em>k&lt;/em> = 3 -&amp;gt; &lt;code>[5,6,7,1,2,3,4]&lt;/code>&lt;br>
先不論其他的部分，我們可以發現5&lt;del>7從最尾端3個變成最前面的3個了；&lt;br>
與此同時，1&lt;/del>4自然從最前面4個變成最尾端4個。&lt;br>
我們先不論大家的順序，先將整個陣列倒過來的話，&lt;br>
可以先達到1&lt;del>4，5&lt;/del>7分別占據目標的區塊的效果：[&lt;strong>7,6,5&lt;/strong> ,4,3,2,1]。&lt;br>
接著再比對一下，發現&lt;strong>區塊是對了，但各自剛好被顛倒過一次&lt;/strong> ，&lt;br>
那麼我們&lt;strong>再對7&lt;del>5及4&lt;/del>1分別各進行一次反轉&lt;/strong> ，就會得到我們要的結果。&lt;/p>
&lt;p>所以整個流程就會變成：&lt;/p>
&lt;ol>
&lt;li>將&lt;strong>整個陣列&lt;/strong> 進行反轉&lt;/li>
&lt;li>將&lt;strong>前k個數&lt;/strong> 進行反轉&lt;/li>
&lt;li>將&lt;strong>後l-k個數&lt;/strong> 進行反轉&lt;/li>
&lt;/ol>
&lt;p>反轉是很基本的操作，希望讀者能熟練掌握，&lt;br>
原則上利用two pointer的方式，&lt;strong>每次將兩個元素進行交換&lt;/strong> ，&lt;br>
並對pointer位置進行遞增/遞減的操作，&lt;strong>直到相交&lt;/strong> 為止。&lt;br>
(例: [&lt;strong>1&lt;/strong> ,2,3,&lt;strong>4&lt;/strong> ]-&amp;gt;[4,&lt;strong>2&lt;/strong> ,&lt;strong>3&lt;/strong> ,1]-&amp;gt;[4,&lt;em>3&lt;/em>,&lt;em>2&lt;/em>,1])&lt;br>
Java的部分的兩數交換需要宣告一個暫存值tmp(temp)，&lt;br>
Python的部分則可直接使用a, b = b, a的方式進行交換。&lt;br>
最後，操作之前不要忘記將k先取除以l的餘數。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0ed5ed74bd3ebc7331d2d781d201c853.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/b88c9b313855bb792cd4638c573d1036.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)(如果是使用3次reverse的方法))&lt;/p>
&lt;p>「如不限制空間複雜度必須O(1)？」&lt;br>
(可以參照上面Python程式碼中註解的做法)&lt;/p>
&lt;h2 id="相似及延伸">相似及延伸
&lt;/h2>&lt;ol>
&lt;li>&lt;strong>0031. Next Permutation&lt;/strong> (可以用到swap跟reverse的操作來解題)&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;br>
(歡迎提供意見協助更正歐~)&lt;/strong>&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 26 Dynamic Programming (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-26-dynamic-programming-5/</link><pubDate>Wed, 07 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-26-dynamic-programming-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 26 Dynamic Programming (5)" />&lt;p>&lt;strong>0096. Unique Binary Search Trees (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given &lt;em>n&lt;/em>, how many structurally unique &lt;strong>BST’s&lt;/strong> (binary search trees) that store values 1 … &lt;em>n&lt;/em>?&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Given n = 3, there are a total of 5 unique BST&amp;#39;s:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1 3 3 2 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \ / / / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3 2 1 1 3 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / / \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 1 2 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>還記得什麼是二元搜尋樹嗎？&lt;br>
不知道的話，可以翻閱前面的&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"
>第16篇&lt;/a>的介紹歐！&lt;br>
簡言之，一個合法的BST除了&lt;strong>左邊的節點要全小於根節點，右邊的節點要全大於根節點&lt;/strong> 外，&lt;br>
其&lt;strong>左右子樹也要是BST&lt;/strong> 才行。&lt;br>
觀察n=3的狀況，我們可以將其歸納成3類：&lt;br>
以1為根節點/以2為根節點/以3為根節點。&lt;/p>
&lt;p>首先是1為根節點的狀況：&lt;br>
左邊沒有比其小的節點，故只有一種可能；&lt;br>
右邊有2跟3的組合，相當於n=2的時候的狀況(2種)。&lt;br>
(2跟3等價於1跟2兩個節點會有的組合)&lt;/p>
&lt;p>再來是2為根節點的狀況：&lt;br>
左邊只有1種可能(1這個節點)；&lt;br>
右邊也只有1種可能(3這個節點)。&lt;/p>
&lt;p>最後是3為根節點的狀況：&lt;br>
左邊是1跟2的組合(2種)，&lt;br>
右邊只有1種可能。&lt;/p>
&lt;p>如果我們將n的組合命名為函式f(n)，&lt;br>
那麼顯然f(0)=1(只有一種可能)，f(1)=1。&lt;/p>
&lt;p>計算n=3的組合算法為：&lt;br>
f(0)*f(2) + f(1)*f(1) + f(2)*f(0)&lt;/p>
&lt;p>掌握這個規律的狀態，我們可以得到f(n)的計算方式：&lt;br>
&lt;strong>f(0)*f(n-1) + f(1)*f(n-2) + … + f(n-1)*f(0)&lt;/strong>&lt;br>
那麼，從f(1)開始起算的話，&lt;br>
我們可以一路疊加將f(1)到f(n-1)都算出來，&lt;br>
最後得到我們要的f(n)。&lt;br>
讓f(n)能夠化成f(n-1)或較小的項次的組合，一路化簡到能直接確認的值，&lt;br>
所以這個就是典型的動態規劃的範例。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/ce5c906a7cd1c392881fc66b17bad400.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/73fc12362e96b3eebddf820bc4de0836.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n²), O(n)&lt;br>
由於計算時兩層迴圈最大都要經歷n，故時間上會和n的平方相關)&lt;/p>
&lt;p>「可以改成&lt;strong>遞迴&lt;/strong> 的方式嗎？」&lt;br>
(可以，我們只要將dp改成字典或HashMap，開一個函式search，&lt;br>
令其在找不到值的時候呼叫自己如 sum += search(i-1) * search(n-i)，&lt;br>
最後也會如同迴圈的解法一樣一路拆解到最底下，&lt;br>
讀者可以自行嘗試看看，實測上兩者速度在實作正確的狀況下，&lt;br>
應該是感受不出太明顯的差異的。)&lt;/p>
&lt;p>&lt;strong>Special Thanks suggestions/corrections from viewers:&lt;/strong>&lt;br>
From Python Taiwan&lt;br>
 曾淯銘: 更正BST的筆誤(連結是對的，本文打錯，是左&amp;lt;根&amp;lt;右，已更正)&lt;br>
 ChenRay Hsieh: 本文的解其實等同於&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E5%8D%A1%E5%A1%94%E5%85%B0%E6%95%B0" target="_blank" rel="noopener"
>Catalan number&lt;/a>，讀者可參考閱讀。&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 25 Array (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-25-array-3/</link><pubDate>Tue, 06 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-25-array-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 25 Array (3)" />&lt;p>&lt;strong>0283. Move Zeroes (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array &lt;code>nums&lt;/code>, write a function to move all &lt;code>0&lt;/code>&amp;rsquo;s to the end of it while maintaining the relative order of the non-zero elements.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [0,1,0,3,12]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,3,12,0,0]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note&lt;/strong> :&lt;/p>
&lt;ol>
&lt;li>You must do this &lt;strong>in-place&lt;/strong> without making a copy of the array.&lt;/li>
&lt;li>Minimize the total number of operations.&lt;/li>
&lt;/ol>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個陣列nums並要求將所有當中的0全部都放到最後面，&lt;br>
且必須保持所有非0的元素的原有相對排列。&lt;br>
另外Note中還要求必須要in-place且最小化總共操作的次數。&lt;/p>
&lt;p>這題其實有很多變形，雖然簡單，&lt;br>
務必請留意題目所要求的條件，不要倉促作答。&lt;/p>
&lt;p>首先題目強調必須in-place(in-place的部分&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-5-in-place-22d309007d15?source=friends_link&amp;amp;sk=f212fac9996b0a8b461ecad247deb90b" target="_blank" rel="noopener"
>先前的文章&lt;/a>有提到過)，&lt;br>
故諸如開一個ArrayList/List來將所有非0的部分一個一個存起來的方法，&lt;br>
在這裡就完全行不通了。&lt;/p>
&lt;p>直覺上或許讀者會想到諸如以下的方法：&lt;/p>
&lt;ol>
&lt;li>從頭開始找到第一個0元素(位置假設為a)&lt;/li>
&lt;li>找到從這個0元素以後第一個非0的元素&lt;/li>
&lt;li>將兩者交換&lt;/li>
&lt;li>從a+1開始找到下一個0元素&lt;/li>
&lt;li>再找到從這個0元素以後第一個非0的元素&lt;/li>
&lt;li>按照這樣的邏輯直到沒有更多的0元素，或找到0元素以後，&lt;br>
其後沒有非0的元素為止。&lt;br>
(上面的方法沒有很嚴謹，因為1有可能就已經找不到0元素了，&lt;br>
僅為大概的範例)&lt;/li>
&lt;/ol>
&lt;p>但這樣的方法對每一個0元素都有可能需要掃瞄過一整個陣列，&lt;br>
總體的時間複雜度會來到O(N^2)。&lt;/p>
&lt;p>有更好的方法嗎？&lt;br>
我們可以先考慮：&lt;br>
如果我們將原先的陣列當成額外開的ArrayList或List來使用的話呢？&lt;br>
先將所有的非0值從index 0開始放入，直到沒有非0的元素為止，&lt;br>
接著，和開新的空間不同，&lt;strong>後面多出來的部分相當於被排開的0&lt;/strong> ，&lt;br>
所以我們要&lt;strong>將後面的值全部設為0&lt;/strong> 。&lt;/p>
&lt;p>這麼做只需要記錄當前非0的部分放到哪邊，在其後再進行補0的動作即可，&lt;br>
最極端的狀況是全部都是0(即完全不用更動陣列)，&lt;br>
以及全部都非0(即將原本的位置複寫相同的數字一次)；&lt;br>
一旦中間有出現0的狀況，只代表其後的數字被往前挪一格，&lt;br>
讀者可以紙筆稍加操作看看即可確認不會有非0的數字會被吃掉XD~&lt;/p>
&lt;p>我們使用了index來記錄下一個即將被寫入非0數字的位置，&lt;br>
遍歷整個陣列/串列，當元素非0時，則將其寫入index的位置，&lt;br>
並遞增index，其程式碼如下所示。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7fa4f56e68afd079bb25982caaeed835.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/54c828ae9591fe19db0d48a85e71c5fb.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1)，因為最多只須掃過陣列兩次即可)&lt;/p>
&lt;p>「如果不要求順序保持相同的話呢？」&lt;br>
(使用two pointer的方式，i由頭至尾，j由尾至頭，&lt;br>
分別找到0和非0的元素進行交換，直到彼此交會即可。&lt;br>
時間/空間複雜度相同但可預期因只須掃過一次陣列，有機會較快)&lt;/p>
&lt;p>「如果不要求要in-place呢？」&lt;br>
(以python為例: &lt;br>
res=[x for x in nums if x != 0]&lt;br>
res += (len(nums)- len(res))*[0]&lt;br>
(後面再接上對應個數的0即可)&lt;br>
(時間/空間複雜度O(N),O(N))&lt;/p>
&lt;p>所以，有些題目簡單歸簡單，看到的時候，還是請留心限制條件，&lt;br>
它有可能跟你熟悉的題目有些出入！有時候一旦限制條件不同，&lt;br>
可以用的手段和時間/空間複雜度可能就會完全不同了！&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 24 Dynamic Programming (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-24-dynamic-programming-4/</link><pubDate>Mon, 05 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-24-dynamic-programming-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 24 Dynamic Programming (4)" />&lt;p>&lt;strong>0063. Unique Paths II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>A robot is located at the top-left corner of a &lt;em>m&lt;/em> x &lt;em>n&lt;/em> grid (marked ‘Start’ in the diagram below).&lt;/p>
&lt;p>The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).&lt;/p>
&lt;p>Now consider if some obstacles are added to the grids. How many unique paths would there be?&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-24-dynamic-programming-4/image-001.png"
width="400"
height="183"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-24-dynamic-programming-4/image-001_hu55fa05334d237aad285f51bab6b81011_9825_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-24-dynamic-programming-4/image-001_hu55fa05334d237aad285f51bab6b81011_9825_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="218"
data-flex-basis="524px"
>&lt;/p>
&lt;p>An obstacle and empty space is marked as &lt;code>1&lt;/code> and &lt;code>0&lt;/code> respectively in the grid.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> &lt;em>m&lt;/em> and &lt;em>n&lt;/em> will be at most 100.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,0,0],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,1,0],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [0,0,0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>There is one obstacle in the middle of the 3x3 grid above.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>There are two ways to reach the bottom-right corner:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1. Right -&amp;gt; Right -&amp;gt; Down -&amp;gt; Down
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2. Down -&amp;gt; Down -&amp;gt; Right -&amp;gt; Right
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>這題基本上就是前面Unique Paths I的續集，在棋盤上存在障礙物。&lt;br>
如果我們考慮某個點是障礙物的話，其造成的影響會是什麼呢？&lt;br>
建議讀者可以自行畫幾條路徑試試看，這個狀況下，&lt;br>
會造成的結果為：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>能到達該點的方法數為0(已經是障礙物了)&lt;/strong>&lt;/li>
&lt;li>承1，因此對1個點來說，&lt;br>
加總的方式應該是&lt;strong>先看這個點是否是障礙物&lt;/strong> ，&lt;br>
不是的話，才需要考慮它&lt;strong>左邊&lt;/strong> 和&lt;strong>上面&lt;/strong> 是否有可以到達的方法數。&lt;/li>
&lt;/ol>
&lt;p>我們最開始先檢查輸入的方格是否正常，且第一個如果被擋的話，&lt;br>
代表完全走不出去，直接回傳0即可。扣除掉這個狀況的話，&lt;br>
接著從原點開始的方法數就是&lt;strong>1&lt;/strong> 。接下來便可由此開始進行dp。&lt;/p>
&lt;p>先定義好儲存path的二維陣列並將1放到原點，&lt;br>
依序對每個方格檢查，只要確定它不是障礙物，&lt;br>
就依照判斷將該加上去的部分加上去。&lt;br>
(加到左邊或上面是障礙物的點沒關係，因為它已經是0了)&lt;/p>
&lt;p>全部遍歷過一次以後，回傳右下角的值即可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/411fc4ae91b90163db883bdce4814478.js">&lt;/script>
&lt;p>Python的部分要特別留意二維列表的生成，&lt;br>
請勿使用[[0]*n]*m，這樣在第二層會&lt;strong>產生m個指向相同位址的列表&lt;/strong> 。&lt;br>
(第一層不會，因為0的部分還是基本型態而非物件)&lt;br>
(也就是動其中一個row會同步改到其他的row)&lt;br>
我們可以使用二層的List Comprehension來處理，或者第一層用*，&lt;br>
第二層用List Comprehension亦可，這裡示範後者。&lt;br>
(實測上兩者&lt;strong>速度並無明顯差異&lt;/strong> )&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/6dc408a8fad92f997a818d48348b0191.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(m*n), O(m*n)，因我們會遍歷整個二維列表，&lt;br>
且需要另一個二維列表來儲存中間的方法數)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 23 Array (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-23-array-2/</link><pubDate>Sat, 03 Aug 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-23-array-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 23 Array (2)" />&lt;p>&lt;strong>0229. Majority Element II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an integer array of size &lt;em>n&lt;/em>, &lt;br>
find all elements that appear more than &lt;code>⌊ n/3 ⌋&lt;/code> times.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> The algorithm should run in linear time and in O(1) space.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [3,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,1,1,3,3,2,2,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [1,2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>跟上一篇相似，這篇將出現超過二分之一改變為三分之一，&lt;br>
要求求所有出現超過三分之一次數的數值，&lt;br>
這使得可能超過三分之一的種類會變成2種，但並不保證一定會有2種。&lt;br>
按照上一篇的摩爾投票算法的思路，&lt;br>
我們可以取2個數(n1, n2)暫存，&lt;br>
每次拿一個新的來檢驗並處理每三個相消的動作，&lt;br>
這樣我們即可以保證留下來的會有當中超過三分之一的元素。&lt;/p>
&lt;p>要特別留意的是，兩個數有可能會是一致的，&lt;br>
且不一定每次都存在2種超過三分之一的元素，&lt;br>
所以最後我們要個別重新確認留在n1及n2上的元素，&lt;br>
其個數是否有超過三分之一。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/1af85e5212b5fab8c8380f9afdb9138c.js">&lt;/script>
&lt;p>Python的部分，我們這邊除了同於Java的解法以外，&lt;br>
再提供一個簡單的作法：使用Counter。&lt;br>
利用Counter可以將一個列表轉換成Counter物件，&lt;br>
儲存的方式是(key:元素 及 value: 該元素出現的次數)&lt;br>
在迴圈中的取用基本上跟字典類似。&lt;br>
只要檢查每個元素出現次數是否大於三分之一的數量即可加至結果。&lt;/p>
&lt;p>(請留意如果認真按照題目要求的話，&lt;br>
這個解法因為會佔用額外&lt;strong>O(n)&lt;/strong> 空間，&lt;br>
故不是一個在O(1)空間內可以完成的算法。)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/37250d6e8e15407b7995ff8db1e78b91.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n), O(1)。&lt;br>
要經過整個陣列兩次，且額外並沒有需求常數次數以外的空間)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 22 Array (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-22-array-1/</link><pubDate>Wed, 31 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-22-array-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 22 Array (1)" />&lt;p>&lt;strong>0169. Majority Element (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of size &lt;em>n&lt;/em>, find the majority element. The majority element is the element that appears &lt;strong>more than&lt;/strong> &lt;code>⌊ n/2 ⌋&lt;/code> times.&lt;/p>
&lt;p>You may assume that the array is non-empty and the majority element always exists in the array.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [3,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,2,1,1,1,2,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>嗨，大家今天過得好嗎？歡迎回到軟工宅宅(誤)。&lt;br>
接下來的幾題我們會著墨一下有關陣列(Array)或列表(List)相關的內容。&lt;/p>
&lt;p>題目給定了一個長度為n的陣列，&lt;br>
已知當中有一個majority element(佔大多數的元素)，&lt;br>
這個數的個數會多過於&lt;code>⌊ n/2 ⌋&lt;/code>。&lt;br>
(此符號代表向下取整數，如&lt;code>⌊ 5/2 ⌋&lt;/code>=2。&lt;br>
別忘了是more than，所以如果n是5的話，&lt;br>
代表majority element至少要有3個)&lt;/p>
&lt;p>題目還貼心地告訴我們，可以假定陣列不是空的，&lt;br>
且一定存在majority element，所以這邊可以省掉一些常用的檢查。&lt;/p>
&lt;p>怎麼解這題呢？&lt;br>
一般來說的直覺可能會想使用HashMap來解(Python則用dict)，&lt;br>
將每個數塞入HashMap/字典中，最後找最大的那個數就是了。&lt;br>
這麼做的時間複雜度為O(n)，空間複雜度亦為O(n)，&lt;br>
因為插入耗費的時間為O(1)，插入n個數即為O(n)，&lt;br>
同時，我們只能保證最多有n - &lt;code>⌊ n/2 ⌋&lt;/code>的不同種類的數，&lt;br>
所以空間上還是保持在O(n)的複雜度。&lt;br>
在中途過程中在去檢驗是否有超過半數的element也可以，&lt;br>
但由於過程不保證會先碰到超過半數，所以額外檢驗的時間，&lt;br>
和省下來後面可能不用做完的時間相比，是不能肯定誰效率比較好的。&lt;/p>
&lt;p>那麼，有沒有比較節省空間的做法呢？&lt;br>
有的！這裡介紹一個演算法，全名叫做：&lt;br>
Boyer–Moore majority vote algorithm(摩爾投票算法)&lt;br>
這個算法的核心在於，&lt;br>
&lt;strong>刪去一個數列中的兩個不同的數字，不會影響該數列的majority element。&lt;/strong>&lt;/p>
&lt;p>假想有一群人要投票，候選人有A、B、C，假設A已知會過半數的話，&lt;br>
任取其中2個人取消他們的投票資格，會有以下的狀況：&lt;/p>
&lt;ol>
&lt;li>被取消資格的是B跟C -&amp;gt; 顯然A還是過半數(而且比例更高了XD)&lt;/li>
&lt;li>被取消資格的是(A, B)或(A, C) -&amp;gt; 一個投A的和一個不投A的同步被排除，所以無法改變A會過半數的狀況。&lt;/li>
&lt;/ol>
&lt;p>同理，在不只3個候選人(數字)的時候，每次取2個人取消投票資格(移除)，亦無法改變投票結果(A還是會是majority element)。&lt;/p>
&lt;blockquote>
&lt;p>註：&lt;br>
所以我們可以知道，當你跟你的家人政治立場不同時，&lt;br>
只有兩個人的狀況下都不去投票是沒有用的，&lt;br>
有用的方式是在&lt;strong>投票前夕帶著跟你立場相反的家人們出國去玩&lt;/strong> ，&lt;br>
&lt;strong>多於1人時，每多一個人你就多賺一張選票差距&lt;/strong> ，但你的荷包可能會哭。&lt;br>
(不要說是我教的！)&lt;/p>
&lt;/blockquote>
&lt;p>依此，我們可以使用下列的方式來進行陣列運算：&lt;/p>
&lt;ol>
&lt;li>取出第一個數放到一個暫存的變數(res)，&lt;br>
將計數器(cnt)設定為1，代表這個數出現1次。&lt;/li>
&lt;li>取出下一個數nums[i]，如果和res相等，則將計數器+1；&lt;br>
如果和res不同，且計數器&amp;gt;0時，將計數器-1；(代表取這兩個數成對移除)&lt;br>
如果和res不同但是計數器=0時，將res更改為nums[i]並將計數器+1(代表res已經用完了，現在還沒被移除的是nums[i])&lt;/li>
&lt;li>反覆進行步驟2直到陣列結尾，剩下的res即為答案。&lt;br>
(因為兩兩移除到最後一定是非majority element的先被移光)&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/58ac9d04e78f53491f0a22498aa39637.js">&lt;/script>
&lt;p>還有另一種作法，是將陣列進行排序，&lt;br>
無論如何majority element一定會通過中間的位置。&lt;br>
這種方式的時間複雜度為O(nlogn)，空間複雜度視你的呼叫方式而定，&lt;br>
可能是O(1)也可能是O(n)(將排序的結果放到別的地方的話)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/b0f289f5419eb98e9acb1ea407dd5301.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(n), O(1)，除了一些變數以外我們沒有使用到額外的空間)&lt;/p>
&lt;p>「各方法的優劣為何？」&lt;br>
(可以參照&lt;a class="link" href="https://leetcode.com/problems/majority-element/solution/" target="_blank" rel="noopener"
>Solution&lt;/a>的頁面，這篇作者分析的內容很完整)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 21 Dynamic Programming (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-21-dynamic-programming-3/</link><pubDate>Mon, 29 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-21-dynamic-programming-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 21 Dynamic Programming (3)" />&lt;p>&lt;strong>0062. Unique Paths (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>A robot is located at the top-left corner of a &lt;em>m&lt;/em> x &lt;em>n&lt;/em> grid (marked ‘Start’ in the diagram below).&lt;/p>
&lt;p>The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).&lt;/p>
&lt;p>How many possible unique paths are there?&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-21-dynamic-programming-3/image-001.png"
width="400"
height="183"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-21-dynamic-programming-3/image-001_hu55fa05334d237aad285f51bab6b81011_9825_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-21-dynamic-programming-3/image-001_hu55fa05334d237aad285f51bab6b81011_9825_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="218"
data-flex-basis="524px"
>&lt;/p>
&lt;p>Above is a 7 x 3 grid. How many possible unique paths are there?&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> &lt;em>m&lt;/em> and &lt;em>n&lt;/em> will be at most 100.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: m = 3, n = 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1. Right -&amp;gt; Right -&amp;gt; Down
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2. Right -&amp;gt; Down -&amp;gt; Right
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3. Down -&amp;gt; Right -&amp;gt; Right
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: m = 7, n = 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 28
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>有一個m x n大小的格子，其左上處有一台機器人，每次機器人僅能選擇往右或往下走，目的是要達到右下角的Finish的位置，題目問說當給定m和n時，有多少種不同的方法可以從左上走到右下？&lt;/p>
&lt;p>這題也是典型的動態規劃題目，只要稍稍思考一下，&lt;br>
我們就能發現一件事情：&lt;br>
走到任何一個點的方式，取決於&lt;strong>走到其左的方法數&lt;/strong> 加上&lt;strong>走到其上的方法數&lt;/strong> 。&lt;/p>
&lt;p>那麼，再思考一下走到左邊跟走到上面會有重複的狀況嗎？顯然是不會的。&lt;br>
因為走到一個格子的左邊顯然和走到其上面會相差往下走一格及往右走一格的動作，而且因為機器人也只能往下或往右，所以沒辦法再回頭，故已經走過的部分不可能再繞得回來。&lt;/p>
&lt;p>在這個狀況的特例有幾個：&lt;/p>
&lt;ol>
&lt;li>機器人所站的&lt;strong>原點&lt;/strong> (按我們的定義一開始就在此，故可以將方法數定為1)&lt;/li>
&lt;li>&lt;strong>最左邊&lt;/strong> 的一排格子 (僅取決於走到其上面格子的方法數)&lt;/li>
&lt;li>&lt;strong>最上面&lt;/strong> 的一排格子 (僅取決於走到其左邊格子的方法數)&lt;/li>
&lt;/ol>
&lt;p>而實際上從第1點來推算的話，&lt;br>
我們可以知道最左邊一排跟最上面到達的方法數&lt;strong>都會是1&lt;/strong> 。&lt;br>
所以我們可以先將這三點的部分先設定為1，接著從較小的index開始沿途把到達每個點的方法算出來，直到最後將整個grid算完。&lt;/p>
&lt;p>在這個方法下，我們需要一個m x n的陣列用以儲存方法數，為了方便起見，我們就直接叫它dp，讀者亦可命名為grid，&lt;strong>請留意這些命名都只是方便起見，只要你的命名能和面試官溝通即可，我們現在並不是在寫一個大的project，簡短命名並告知你的面試官你的目的是筆者推薦的做法。&lt;/strong>&lt;/p>
&lt;p>最後僅需回傳dp[m-1][n-1]即可。&lt;br>
(註:由於這邊row跟column的交換並不影響結果，&lt;br>
故我們這邊不特別去在意m和n的前後順序。)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/b513a1c2d12e6d570fd10c00ac971686.js">&lt;/script>
&lt;p>Python這邊收尾的時候可以用dp[-1][-1]來表示尾端的元素，&lt;br>
宣告的時候則採用list comprehension(列表解析式/列表表達式)。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/61377205ae47e892c78a4e38dfa68ee2.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(均為O(m*n))&lt;/p>
&lt;p>「空間複雜度是否可以降低？」&lt;br>
(理論上可以，因為實際每次處理的關連部分僅有兩行或兩列，&lt;br>
反覆利用應該可以讓空間需求降低到O(m)或O(n)，但時間複雜度一致)&lt;/p>
&lt;p>「是否有更簡單的解？」&lt;br>
(DP的話，沒有，數學的話，有。&lt;br>
 假設往下叫D，往右叫R，求不同走法的過程，&lt;br>
即相當於在求**(n-1)個D和(m-1)個R的不同排列方法** ，&lt;br>
故答案會是(m-1+n-1)!/(m-1)!(n-1)!，&lt;br>
此時&lt;strong>空間複雜度為O(1)，時間複雜度為O(m+n)&lt;/strong> 。&lt;br>
但階乘的部分當值過大時有可能會有超過int的可能性。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 20 Tree (6)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-20-tree-6/</link><pubDate>Sat, 27 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-20-tree-6/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 20 Tree (6)" />&lt;p>&lt;strong>0110. Balanced Binary Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, determine if it is height-balanced.&lt;/p>
&lt;p>For this problem, a height-balanced binary tree is defined as:&lt;/p>
&lt;blockquote>
&lt;p>&lt;em>a binary tree in which the depth of the two subtrees of&lt;/em> every &lt;em>node never differ by more than 1.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;p>Given the following tree &lt;code>[3,9,20,null,null,15,7]&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 20
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 15 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Return true.&lt;/p>
&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;p>Given the following tree &lt;code>[1,2,2,3,3,null,null,4,4]&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Return false.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，試檢查其是否為高度平衡的狀態。&lt;br>
前面已經提到過很多次，若是一棵樹長得不夠平均(例如都長在同一邊)，那麼在進行一些操作的時候會相當耗時間，&lt;br>
這也是為什麼我們會在意一棵樹高度是否平衡的原因。&lt;/p>
&lt;p>而題目給的條件其實以更常見的定義來說，會定義成如下所述。&lt;br>
假如底下3點成立，一棵非空的二元樹就被稱作是平衡的：&lt;/p>
&lt;ol>
&lt;li>二元樹的&lt;strong>左子樹是平衡的&lt;/strong>&lt;/li>
&lt;li>二元樹的&lt;strong>右子樹是平衡的&lt;/strong>&lt;/li>
&lt;li>二元樹的&lt;strong>左右子樹高的差不大於1&lt;/strong> 對於一個樹的高度(或稱作深度)，&lt;br>
是指從樹的根節點走到葉節點的最大長度，所以基於這點，我們的流程應該是從根節點往下，檢查以每個節點為基準的左右子樹高的差均不大於1，該二元樹即為平衡的，反之則為不平衡。&lt;/li>
&lt;/ol>
&lt;p>依此，我們會需要知道除了根以外，每個節點的深度，&lt;br>
故可以簡單利用遞迴來操作：&lt;/p>
&lt;p>先試寫看看maxdp這個函式的虛擬碼(假設你要求root這個node的深度)：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>maxdp(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> l = maxdp(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> r = maxdp(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return max(l, r) + 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當我們要求某個節點的深度時，&lt;br>
&lt;strong>就相當於求其左右兩邊子樹深度的較大值+1&lt;/strong> 。&lt;br>
(+1是因為經過了自己這個節點)&lt;/p>
&lt;p>回到我們原本的問題，我們想要求左右子樹的深度差不能大於1的話，只需要在maxdp函式中增加去判斷左右深度差即可。&lt;br>
我們同時可以使用一個變數res來記錄是否已經發生不平衡的情況，&lt;br>
一旦發生，其實可以不用繼續往下做。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>let res = true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>maxdp(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if (root == NIL or !res) return 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> l = maxdp(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> r = maxdp(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if (abs(l-r) &amp;gt; 1) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res = false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return max(l, r) + 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在一開始的解答的isBalanced函式中呼叫maxdp，&lt;br>
最後將res回傳即可得到答案。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e458838d8b04d2e4ade2f3c1d13beb4e.js">&lt;/script>
&lt;p>Python這邊展示了一個再進一步的思路：&lt;br>
如果我們已經發現不平衡的狀況，可以使用-1做為代表，因為深度只可能大於或等於0，那麼，只要每次檢查是否出現-1，就不用使用額外的res變數來儲存結果，我們只需要檢查回傳是否為-1就可以判定二元樹是不是平衡了！&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9e60476056da953f64f4acfd5cd41be9.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(最差狀況是樹很平衡，每一層都要檢查，時間複雜度是O(N)&lt;br>
自行宣告的額外空間是O(1)，但遞迴中需有Call Stack，&lt;br>
最糟的狀況也是O(N)(全擠在同一邊))&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 19 Tree (5)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-19-tree-5/</link><pubDate>Thu, 25 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-19-tree-5/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 19 Tree (5)" />&lt;p>&lt;strong>0111. Minimum Depth of Binary Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, find its minimum depth.&lt;/p>
&lt;p>The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> A leaf is a node with no children.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;p>Given binary tree &lt;code>[3,9,20,null,null,15,7]&lt;/code>,&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 20
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 15 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>return its minimum depth = 2.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，要求找到最小的深度，也就是從根節點到最近的葉節點的路徑長。(&lt;strong>葉&lt;/strong> 節點是指它底下&lt;strong>沒有其他小孩&lt;/strong> 了)&lt;br>
上一題我們講解了一題Hard的題目，讓我們稍微喘口氣，&lt;br>
來看個這個比較基本的題目吧！&lt;/p>
&lt;p>這題概念並不複雜，只要稍微弄明白要被遞迴的主體即可。&lt;br>
對一個節點來說，我們已經知道所謂的深度就是從&lt;strong>根走到這個節點的長度&lt;/strong> 。&lt;br>
既然我們要求最小的路徑長度，可以選擇的方式就是分別看兩邊有多深，&lt;br>
最後&lt;strong>選擇較小的那邊&lt;/strong> ，加上1即可。(因為從根走到根的左/右節點要計算到)&lt;br>
那麼，左右各自有多深同樣也要取最小的路徑，&lt;br>
故一樣使用相同的方法再往下遞迴。&lt;/p>
&lt;p>依此嘗試寫成遞迴的虛擬碼：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>minDepth(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> l = minDepth(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> r = minDepth(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l == 0 or r == 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return l + r + 1 // 等同於取非NIL那條的路徑或取1(當左右都是NIL)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> else
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return min(l, r) + 1 // 左右都有時取較小的路徑
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>再化成程式碼如下：&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/082c58b525465438fc4e67ad655a7350.js">&lt;/script>
&lt;p>Python的部分使用判斷是否是None來處理，&lt;br>
本質上是一樣的，讀者可依個人喜好來選用寫法。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/05b0eeb98bda057b1505fee9d39bd457.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(由於必須遍歷所有節點，時間複雜度為O(N)，空間複雜度則依照stack深度而定，最糟的狀況也是O(N)，最好的狀況則是O(logN))&lt;/p>
&lt;p>「可以用迭代解嗎？」&lt;br>
可以，但比較難想，有興趣的讀者可以嘗試使用我們還沒有仔細講過的&lt;strong>level-order traversal&lt;/strong> 來解此題，大致的思路是使用Queue來&lt;strong>保存相同深度的所有節點&lt;/strong> ，並且用另一個Queue和level進行記錄，一旦在某次出現了&lt;strong>node.left和node.right均為NIL&lt;/strong> 的狀況，代表在這層就遇到&lt;strong>葉子&lt;/strong> ，那麼就可以&lt;strong>回傳level即為解答&lt;/strong> 。&lt;br>
這麼做的時間複雜度和空間複雜度均和&lt;strong>最小深度&lt;/strong> 有關，若最小深度為D，&lt;br>
時間空間複雜度均為O(2^D)，雖然看起來比較可怕，&lt;br>
但其實最糟的狀況是這棵二元樹是平衡的，這時2^D-1 = N；&lt;br>
而其他狀況下複雜度肯定小於O(N)。&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 18 Tree (4)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-18-tree-4/</link><pubDate>Tue, 23 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-18-tree-4/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 18 Tree (4)" />&lt;p>&lt;strong>0124. Binary Tree Maximum Path Sum (Hard)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a &lt;strong>non-empty&lt;/strong> binary tree, find the maximum path sum.&lt;/p>
&lt;p>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>at least one node&lt;/strong> and does not need to go through the root.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,2,3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [-10,9,20,null,null,15,7]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> -10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9 20
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 15 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: 42
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，試求其上最大的路徑和的值。&lt;br>
所謂路徑，就是在二元樹上任意挑兩個節點，&lt;strong>從一個節點走到另一個節點，包含它們自己，所經過的所有節點值的和。&lt;/strong>&lt;br>
最小的條件是兩個節點相同，這時候的路徑長等同於這個節點的值。&lt;/p>
&lt;p>嫌前面太簡單了嗎？別急，Hard等級的題目這不就來了嗎XD&lt;br>
在講解以前，建議讀者先思考一下有沒有任何頭緒並寫下來，再接著往下面看分析，相信會有比較好的收穫。&lt;/p>
&lt;p>3~&lt;/p>
&lt;p>2~&lt;/p>
&lt;p>1~&lt;/p>
&lt;p>開始囉！&lt;/p>
&lt;p>如果我們多拿幾組節點來進行觀察，會發現從一個節點要走到另一個節點，要先經過它們最低的共同祖先節點(這邊指從雙方往上走第一個碰頭的位置)，再走下來才行。&lt;br>
以Example 1來說，2和3的最低共同祖先是1，&lt;br>
以Example 2來說，15和7的最低共同祖先是20。&lt;/p>
&lt;p>那麼，我們怎麼決定兩個節點的路徑長呢？&lt;br>
假設我們知道AB兩個節點的話，它們一定會有一個最低的共同祖先節點，&lt;br>
當中&lt;strong>可能是A或B自身，也可能是其他節點&lt;/strong> (如前面的範例就都是其他節點，而如果取的是-10跟15的話那最低的共同祖先節點就是-10)，&lt;br>
所以&lt;strong>每個節點都可以有做為節點的最低共同祖先節點的可能&lt;/strong> 。&lt;/p>
&lt;p>我們姑且將最低共同祖先節點叫做中繼點好了，比較方便XD&lt;br>
接著，將不含中繼點的左邊的最大路徑和叫做l，右邊的最大路徑和叫做r，對於某個中繼點(node n)而言：&lt;/p>
&lt;p>通過中繼點n的最大路徑和 = max(n.val, n.val + l, n.val + r, n.val + l + r)&lt;br>
(因為l或r都有可能是負的，所以要把這四種都考慮在內)&lt;/p>
&lt;p>接著我們要考慮的是，&lt;strong>如果中繼點是別的點而不是現在這個點&lt;/strong> ，&lt;br>
我們只是&lt;strong>經過&lt;/strong> 它但想知道&lt;strong>包含這個點往下走最大路徑和&lt;/strong> 是多少的話，&lt;br>
那我們只能去考慮&lt;strong>n.val/n.val+l/n.val+r&lt;/strong> 這三種狀況。&lt;br>
(因為n.val+l+r代表這個點是做為中繼點才會有分支)&lt;/p>
&lt;p>所以我們可以嘗試用遞迴的方式解題，從root開始往下走到每個節點，計算&lt;strong>該節點往下走的最大路徑和&lt;/strong> ，並且每經過一個節點就考慮看看這個&lt;strong>節點是中繼點的狀況，一旦發現最大值比現有記錄的大，就更新成新的最大值&lt;/strong> 。&lt;br>
由於用來遞迴的函式是一路優先往下一層節點進入(一直到最底下才能回頭依序得到各自的l跟r)，這種優先往深的方向走的方式我們一般稱為&lt;strong>深度優先搜尋&lt;/strong> (DFS, Depth-First Search)。&lt;/p>
&lt;p>寫成虛擬碼如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>define res
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>maxPathSum(root){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res = root.val
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> dfs(root)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return res
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dfs(n){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> l = (n.left != NIL) ? dfs(n.left) : 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> r = (n.right != NIL) ? dfs(n.right) : 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> m = n.val
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> m = max(m, l + m, r + m) // 單做為經過點的最大路徑和
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res = max(res, m, l + r + n.val) // m已比過3種可能，故只需再考慮中繼點
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return m
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在這個虛擬碼當中，我們&lt;strong>先考慮左右是否還有連接節點&lt;/strong> ，有的話就進行dfs往下找出&lt;strong>經過點&lt;/strong> 的最大路徑和，沒有的話則&lt;strong>補上0&lt;/strong> ；接著先考慮m的部分，再利用已經比過大小的m來和作為中繼點的狀況比較，最後和當前最大路徑和相比並更新結果，完整走完所有流程即可得到回傳的答案。&lt;/p>
&lt;p>Java的部分，這邊使用了if來作比較，實測上和一組一組依序使用Math.max來相比並沒有明顯速度上的區別，讀者可依自己喜好使用。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/53bc92125e7553e0e24feb539bd0151e.js">&lt;/script>
&lt;p>Python的部分，留意呼叫時加上的self.即可，&lt;br>
且max可適用於多個傳入值，比起Java會再方便一點。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/10c2f20cd569a3681552a2a54d57a7a6.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(每個節點均會走過一遍，故時間複雜度為O(N)&lt;br>
除了res, l, r, m以外沒有額外的空間了，自行宣告的空間複雜度為O(1)，&lt;br>
但進入遞迴會用到Stack，最大應該是這棵二元樹的&lt;strong>高度&lt;/strong> ，&lt;br>
也就是最糟的狀況下可以到O(N)，最好的狀況則是O(logN))&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 17 Tree (3)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-17-tree-3/</link><pubDate>Mon, 22 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-17-tree-3/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 17 Tree (3)" />&lt;p>&lt;strong>0094. Binary Tree Inorder Traversal (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, return the &lt;em>inorder&lt;/em> traversal of its nodes’ values.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,null,2,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: [1,3,2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up:&lt;/strong> Recursive solution is trivial, could you do it iteratively?&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個二元樹，題目要求以inorder(中序)方式回傳其節點值。&lt;br>
由於上一題的關係(讀者可以回頭參照&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"
>第16篇&lt;/a>)，我們已經講解過In-order的方式了，原則上就是經過&lt;strong>左邊的部分-&amp;gt;中間的部分-&amp;gt;右邊的部分&lt;/strong> 的順序。&lt;br>
請留意這題輸出並不一定會由小到大(因為並沒有限制是二元搜尋樹)。&lt;/p>
&lt;p>我們先來嘗試遞迴解法，通常較為簡單，這邊重新列出上一篇提到的：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>inorder(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inorder(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(root.val) // Or add/append to the list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inorder(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>若讀者感到不太能夠掌握這個流程的運作，可回頭參考&lt;a class="link" href="https://miro.medium.com/max/685/1*V9LkwYgbTVvGee4k7NkbOQ.gif" target="_blank" rel="noopener"
>第16篇的gif動畫&lt;/a>。&lt;br>
總體而言，&lt;strong>每次我們都會走到當前所能走到的左邊&lt;/strong> ，直到左邊再也沒有node(變成&lt;strong>NIL&lt;/strong> )時，會&lt;strong>回到上一層&lt;/strong> (return)，&lt;strong>印出值&lt;/strong> (或將其放到list中)，接著再&lt;strong>往自身的右邊找&lt;/strong> ；每次同樣的模式操作完以後，我們可以保證對於每個子樹，都是先拿到其左邊的節點值(們)，再來是自身，最後才是右邊的節點值(們)，從而保證這個演算法是得以遵照目標的順序完成的。&lt;/p>
&lt;p>由於我們會使用一個ArrayList或List來存放inorder得到的值，所以下面是採用先宣告再將其放置到另一個遞迴用函式中處理的方式。當然，如讀者只想使用一個函式來遞迴，也可以宣告一個Solution的class變數，這樣就不需要每次傳遞了。兩者各有好處，讀者可依自己喜好決定。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/23f13807df687358e8fb6d15243d76ee.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/02ea8399fd9f59a3038d5822c4db3c4f.js">&lt;/script>
&lt;p>那麼，如果是要求要迭代解(iterative solution)呢？&lt;br>
我們回顧一下前面的作法，遞迴的時候之所以我們能回到上一層，其實是因為我們的程式有記錄上一層的函式的執行狀態，從而在return時能返回到應該繼續的那一行執行。由於&lt;strong>最後一層函式在返回時必須先被呼叫到&lt;/strong> ，所以電腦在儲存時是採用&lt;strong>Stack&lt;/strong> 的形式(因為要後進先出)。(這個堆疊又叫做The Stack或Call stack(呼叫堆疊))&lt;/p>
&lt;p>因此，我們想要能夠不用遞迴解的話，&lt;br>
顯然我們應該要自己使用一個Stack來處理整個流程。&lt;/p>
&lt;ol>
&lt;li>在In-order的流程中，首先我們是先一路走到最左邊的node，&lt;br>
中途經過的node我們應該要將其放進Stack中，這樣才能回到上一層去，&lt;br>
我們將這個node暫時命名為curr(current)。&lt;/li>
&lt;li>curr一路向左最終一定會遇到NIL，表示這排從root一路向左邊走，&lt;br>
沿途的node全數放入到Stack中了。&lt;/li>
&lt;li>那麼我們應該要將最後一個node從Stack中拿出來(因為後進先出，最後一個node應該是最左邊的node才對)，將其放到list當中。&lt;/li>
&lt;li>接著將curr設為自己右邊的node。&lt;/li>
&lt;li>反覆上面的流程，一直到curr和stack都空掉為止。&lt;/li>
&lt;/ol>
&lt;p>寫成虛擬碼如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>create a list named res
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>create a stack named stack
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curr = root
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>while ( curr != NIL or !stack.isEmpty() ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> while (curr != NIL) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> stack.push(curr)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> curr = curr.left
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> curr = stack.pop()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> res.add(curr.val)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> curr = curr.right
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>return res
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="java-1">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/a3d0175fce2ca6f6aaadf7543781d9f2.js">&lt;/script>
&lt;h3 id="python-1">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/c969c8d64b69be7f33a15ed2e19571d5.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
（O(N), O(N)，因為要走訪過整棵樹，且list要儲存整個二元樹攤平的結果）&lt;/p>
&lt;p>「如果我將res放在class Solution的level有什麼優缺點？」&lt;br>
(優點：&lt;br>
有機會速度快一點點，且通常不用傳位址給函式，因為直接能存取到。&lt;br>
缺點：&lt;br>
對整個class均為可見，如果這個函式是要被反複使用的話，&lt;br>
要注意初始化的問題，且也有可能被其他函式修改到。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 16 BST (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/</link><pubDate>Sun, 21 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 16 BST (1)" />&lt;p>&lt;strong>0098. Validate Binary Search Tree (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, determine if it is a valid binary search tree (BST).&lt;/p>
&lt;p>Assume a BST is defined as follows:&lt;/p>
&lt;ul>
&lt;li>The left subtree of a node contains only nodes with keys &lt;strong>less than&lt;/strong> the node’s key.&lt;/li>
&lt;li>The right subtree of a node contains only nodes with keys &lt;strong>greater than&lt;/strong> the node’s key.&lt;/li>
&lt;li>Both the left and right subtrees must also be binary search trees.&lt;/li>
&lt;/ul>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,1,3]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [5,1,4,null,null,3,6]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: The root node&amp;#39;s value is 5 but its right child&amp;#39;s value is 4.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，檢查它是否是二元搜尋樹(Binary Search Tree)。&lt;br>
終於我們來到二元樹的進階版了！&lt;br>
二元搜尋樹如同題目說明，要符合以下三個特性：&lt;/p>
&lt;ol>
&lt;li>任一個節點的&lt;strong>左子樹的所有節點值&lt;/strong> 均&lt;strong>小於&lt;/strong> 該節點自身的值&lt;/li>
&lt;li>任一個節點的&lt;strong>右子樹的所有節點值&lt;/strong> 均&lt;strong>大於&lt;/strong> 該節點自身的值&lt;/li>
&lt;li>二元搜尋樹的&lt;strong>左子樹&lt;/strong> 和&lt;strong>右子樹&lt;/strong> 也都是&lt;strong>二元搜尋樹&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>直觀來說，當我們從某個節點開始往左邊走的時候，一定要比自己小；&lt;br>
反之往右邊走的時候，要比自己大。也因為這個特性，當這棵樹足夠平衡時(節點分布的很均勻時)，會相當有利於&lt;strong>搜尋值，因為每次都幾乎可以排除掉一半的可能性&lt;/strong> 。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-001.png"
width="664"
height="381"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-001_hu0482075b2c4af990a474e02a94f99dbd_20976_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-001_hu0482075b2c4af990a474e02a94f99dbd_20976_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="174"
data-flex-basis="418px"
>&lt;/p>
&lt;p>Binary Serach Tree (Balanced, Complete, Perfect)&lt;/p>
&lt;p>以下面的圖來說，我們想要從一個有15個節點的二元搜尋樹找到58這個值，&lt;br>
就要從根節點開始，每次比較大小，&lt;strong>若58比較大就往右邊走，比較小就往左邊走，直到找到剛好的值，或是碰到NIL(沒有別的節點可以搜尋)為止&lt;/strong> 。&lt;br>
可以看到圖中由於&lt;strong>深度一樣&lt;/strong> 的關係，不論搜尋什麼值，我們可以預期最多就只需要&lt;strong>4次&lt;/strong> 的比對就可以找出任意一個值是否在這棵樹裡面；&lt;strong>每次刪去一半的可能性&lt;/strong> ，所以如果總節點有N個的話，搜尋的複雜度最高即為&lt;strong>O(logN)&lt;/strong> 。&lt;br>
(記得我們提過二元樹不一定非得要全部都有連接節點，這個結果是建立在這棵二元搜尋樹是&lt;strong>平衡(balanced)&lt;/strong> 的狀況，如果這棵樹全部都改成只有左邊的節點的話，結果可是會變成O(N)的！)&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-002.gif"
width="684"
height="438"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-002_hu29b805219f4e9ce747ec067993092586_37478_480x0_resize_box_1.gif 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-002_hu29b805219f4e9ce747ec067993092586_37478_1024x0_resize_box_1.gif 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="374px"
>&lt;/p>
&lt;p>Binary Search for value 58&lt;/p>
&lt;p>我們同樣以上面這棵樹為例，&lt;br>
如果我們想知道它從小到大的節點怎麼排序呢？&lt;br>
這裡就需要使用到In-order Traversal了。&lt;br>
In-order的順序為左-中-右，代表每次我們目標要先拿到左邊的值，接著是中間，最後才是右邊的值；我們最後希望拿到的是[18, 20, 22, 33, 36, 37, 38, 43, 52, 54, 58, 61, 63, 66, 68]的話，我們要先一路走到&lt;strong>最左邊&lt;/strong> 的節點，代表&lt;strong>左邊沒有更小的值&lt;/strong> 了，才能將其印出來(18)，接著第二小的值則是最左邊節點的父節點(20)，而對33來說，還有20的右節點22比它還要小，最後以此類推，每次找到下一個最小值。&lt;br>
寫成虛擬碼如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>inorder(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inorder(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(root.val)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inorder(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>讀者可以嘗試使用上面的遞迴的方式走過一遍，或者參照下面的示意圖，&lt;br>
相信會較為理解這整個流程。留意上面由於當發現NIL的時候就直接return回到了遞迴的上一層，所以就會造成類似&lt;strong>往上走一層&lt;/strong> 的效果。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-003.gif"
width="685"
height="586"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-003_hu9c1c893868e4b65f63a1971e4a389f8c_445711_480x0_resize_box_1.gif 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-16-bst-1/image-003_hu9c1c893868e4b65f63a1971e4a389f8c_445711_1024x0_resize_box_1.gif 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="116"
data-flex-basis="280px"
>&lt;/p>
&lt;p>In-order Traversal&lt;/p>
&lt;p>回到我們的題目，我們已經知道在In-order的狀況下，對於二元搜尋樹可以得到一個由小到大的順序，所以只要記住上一個節點，每次去比較上一個節點和現在走到的節點，當現在的節點跟上一個節點相比較小或相等時，表示這不是二元搜尋樹(因為越後面的節點必須較大才行)；反之，當每個節點都走完沒有錯誤時，這時候就可以確認這個二元樹是二元搜尋樹了。&lt;/p>
&lt;p>寫成虛擬碼如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>let last = NIL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>isValidBST(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if !isValidBST(root.left) return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if last != NIL and root.val &amp;lt;= last.val return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> last = root // 更新上一個節點的位置
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return isValidBST(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Java的寫法部分，我們可以宣告一個class的變數last，&lt;br>
用來存放上一個走到的節點(放在函式內部的話會被洗掉)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4071ba0ef72ce57f097892815c7ae4c5.js">&lt;/script>
&lt;p>Python的部分，請留意到記得在呼叫時使用self的關鍵字，&lt;br>
否則可能會無法在isValidBST中取得last。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/dcfa3b0ff6d68195c8129de4f73a83fa.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
（O(N), O(1)，因為要走過整個BST，&lt;br>
但除了幾個變數外，不需額外的資料結構）&lt;/p>
&lt;p>「可否不用遞迴呢？」&lt;br>
(可以，使用Stack，可以用迴圈讓每次先將root塞入，一路向左邊走將每個左節點放入Stack中，接下來同樣每次取出一個節點，判斷和前一個的大小比較。最後每個左側處理完以後，再將位置移向右節點，迴圈重複即可。)&lt;/p>
&lt;p>「可以不用class的變數來解此題嗎？」&lt;br>
(可以，有一種解法是記錄對某個節點的&lt;strong>最小值和最大值限制&lt;/strong> ，將遞迴函式增加為傳入&lt;strong>root, min, max&lt;/strong> 並隨著每次看到的節點&lt;strong>更新&lt;/strong> 其底下的限制條件，這樣就不需要按照in-order的方式移動，也不需要class的變數。Java的解法這邊收錄 &lt;a class="link" href="https://leetcode.com/ryanswizzle" target="_blank" rel="noopener"
>ryanswizzle&lt;/a>在Leetcode的解法如下。)&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>public class Solution {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> public boolean isValidBST(TreeNode root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return isValid(root, null, null);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> public boolean isValid(TreeNode root, Integer min, Integer max) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if(root == null) return true;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if(min != null &amp;amp;&amp;amp; root.val &amp;lt;= min) return false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if(max != null &amp;amp;&amp;amp; root.val &amp;gt;= max) return false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return isValid(root.left, min, root.val) &amp;amp;&amp;amp; isValid(root.right, root.val, max);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 15 Bitwise Operation (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-15-bitwise-operation-2/</link><pubDate>Thu, 18 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-15-bitwise-operation-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 15 Bitwise Operation (2)" />&lt;p>&lt;strong>0136. Single Number (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a &lt;strong>non-empty&lt;/strong> array of integers, every element appears &lt;em>twice&lt;/em> except for one. Find that single one.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;p>Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [2,2,1]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [4,1,2,1,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個非空的整數陣列，當中每個元素都出現兩次，只有一個出現一次而已，題目要求找出那個單獨的數字。&lt;/p>
&lt;p>在進一步往BST之前，先來一個簡單但一般不會想到的問題。&lt;br>
這題如果我們以暴力法來解的話，假設不用任何額外的資料結構，我們可以每拿一個數字就對整個陣列做比較，直到找到沒有重複的數字為止。但這樣除了時間複雜度會是O(N)以外(對單一數字，所以每個數字都做完就是O(N^2))，最後會發現有可能會有拿到先前拿過一次的數字，所以顯然是不太行的。&lt;/p>
&lt;p>那輔以資料結構呢？&lt;br>
比較常用的方法是使用HashMap(Python則用dict)，為每個數字計數，計數完以後就掃過整個對應，看誰只有被數到一次，就是我們要的答案了。&lt;br>
這個方法要先走訪過一遍陣列，再走訪一遍HashMap或dict，時間/空間複雜度均為O(N)，但還是稍嫌慢了一些。&lt;/p>
&lt;p>那有沒有更厲害的解法呢？有！&lt;br>
要了解這個解法怎麼操作，首先我們需要複習一下&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-11-bitwise-operation-1-3117c4ce925d?source=friends_link&amp;amp;sk=0667ce4030f73468b0ced9961341531d" target="_blank" rel="noopener"
>Bitwise Operation&lt;/a>。&lt;br>
當中的XOR的內容是：將兩個數的每個位元兩兩相對，&lt;strong>一個0一個1的時候，結果會是1，否則結果會是0&lt;/strong> 。&lt;br>
這可以讓數字運算得到一些神奇的特性，第一個特性是：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>a XOR a = 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>我們拿11=1011(二進位)來試試看：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>11 = 1011
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11 = 1011
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11 XOR 11 = 0000 = 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>因為每一位數都相同，XOR後每一位就都會是0。&lt;br>
第二個特性是：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>0 XOR a = a, a XOR 0 = a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>因為一邊都是0，所以那個位數是0或1，端看原先a的位元。&lt;br>
再來其他一些重要的特性是：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>a XOR b = b XOR a (交換律)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(因每個位元的結果端看該位元總共有奇數或偶數個1，和順序無關)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>(a XOR b) XOR c = a XOR (b XOR c) = a XOR (c XOR b) = a XOR c XOR b
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(不論哪邊先做，結果都是看有奇數個1-&amp;gt;結果是1，偶數個1-&amp;gt;結果是0)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(最前面的部分是標準的結合律)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>推而廣之，我們可以得到XOR具有&lt;strong>交換律&lt;/strong> 和&lt;strong>結合律&lt;/strong> 。將它的運算的數字左右調換，或者哪個先做，哪個後做，均不影響結果。&lt;/p>
&lt;p>回到問題來，假設我們目標的答案是r，那麼將陣列中所有的數字XOR起來，會發生什麼事情呢？我們根據前面的已知，將陣列自己調換一下，應該可以變成：&lt;br>
r XOR a XOR a XOR b XOR b XOR c XOR c ……的形式。&lt;br>
(因為怎麼換都不應該影響結果)&lt;/p>
&lt;p>於是，陣列全部XOR的結果會等於r XOR 0 XOR 0 XOR…… = r&lt;br>
(其它的兩兩XOR後會變0)&lt;br>
也就是說，將每個數都進行XOR後，結果會留存下那個唯一單獨的數字。&lt;br>
寫成程式碼如下，宣告變數為0後從index 0開始，或直接將陣列的第一個數指派給它並從index 1開始，實測上沒有特別感受到時間差異，讀者依照自己的喜好和習慣嘗試即可。&lt;/p>
&lt;p>Java的部分用了&lt;strong>語法蜜糖&lt;/strong> ，&lt;br>
int e:nums代表自nums陣列按順序每次拿一個數並交給e。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9ae77bff607f5d3243779d67ba1862fc.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/62526f397d56b25b4d29d5a07fc2fa5e.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(由於只要整個陣列掃過一次就結束了且無須額外的陣列空間，&lt;br>
時間複雜度為O(N)，空間複雜度則為O(1))&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p>
&lt;p>註：感謝&lt;a class="link" href="https://medium.com/@zhoumax" target="_blank" rel="noopener"
>zhoumax&lt;/a>的提醒修正一些敘述和筆誤。&lt;/p></description></item><item><title>從LeetCode學演算法 - 14 Tree (2) / Queue (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-14-tree-2-queue-1/</link><pubDate>Wed, 17 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-14-tree-2-queue-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 14 Tree (2) / Queue (1)" />&lt;p>&lt;strong>0101. Symmetric Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a binary tree, check whether it is a mirror of itself &lt;br>
(ie, symmetric around its center).&lt;/p>
&lt;p>For example, this binary tree &lt;code>[1,2,2,3,4,4,3]&lt;/code> is symmetric:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3 4 4 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>But the following &lt;code>[1,2,2,null,3,null,3]&lt;/code> is not:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> \ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;br>
Bonus points if you could solve it both recursively and iteratively.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個二元樹，要求檢查是否為左右對稱(Symmetric)。&lt;br>
繼前一篇的樹的基本以後，今天同樣來談談另一個基本題，幫助大家熟悉以外，也介紹一個資料結構Queue，用來說明我們怎麼來解迭代解的。&lt;/p>
&lt;p>這邊講的左右對稱是指從根節點將左右切開來看，左邊和右邊恰巧要對稱。&lt;br>
要解決這個問題並不困難，但要留意小細節。&lt;/p>
&lt;p>首先，如果&lt;strong>給定的根是NIL(null/None)&lt;/strong> =&amp;gt; &lt;br>
沒有東西仍然是可以達成左右對稱，所以&lt;strong>必須回傳真值&lt;/strong> (true/True)。&lt;/p>
&lt;p>扣掉這個狀況，再來觀察上面的圖可以發現，根節點毫不影響，&lt;br>
接著要比較的應該是左子樹跟右子樹是否對稱。&lt;br>
和前一題不同，以&lt;code>[1,2,2,3,4,4,3]&lt;/code>為例，要符合對稱的條件，&lt;br>
應該要符合下面三點：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>左子樹根的值=右子樹根的值&lt;/strong>&lt;/li>
&lt;li>&lt;strong>左子樹&lt;/strong> 自己的&lt;strong>左子樹&lt;/strong> (以本例是最左邊的3)要和&lt;strong>右子樹&lt;/strong> 自己的&lt;strong>右子樹&lt;/strong> 對稱&lt;/li>
&lt;li>&lt;strong>左子樹&lt;/strong> 的&lt;strong>右子樹&lt;/strong> 要和&lt;strong>右子樹&lt;/strong> 的&lt;strong>左子樹&lt;/strong> 對稱&lt;/li>
&lt;/ol>
&lt;p>請留意1的部分，&lt;br>
如果&lt;strong>兩者均為NIL&lt;/strong> ，表示下面不用比(空了)且&lt;strong>兩者相等&lt;/strong> ，&lt;br>
這時候應該&lt;strong>回傳真值&lt;/strong> ；而接下來再判斷&lt;strong>其一為NIL&lt;/strong> 的狀況，表示兩者一定不相等(&lt;strong>一個有節點一個是NIL&lt;/strong> )，這個技巧在上一篇同樣有使用到。&lt;br>
&lt;strong>上面都沒成立的話，再判斷兩者值是否相等&lt;/strong> 。&lt;/p>
&lt;p>所以直觀上我們可以寫出這樣的遞迴模式：&lt;br>
(註:留意我們這樣寫只是用來表達整個演算的流程，它通常並不能用來在某個語言執行，這樣的用來表達概念的代碼叫作&lt;strong>虛擬碼(pseudocode)，虛擬碼通常不用嚴格按照特定規範，目的只是要先將你的流程想法釐清為主。&lt;/strong> )&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>isSym(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return isSymmetric(root.left, root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>isSymmetric(l, r) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l == NIL and r == NIL return true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l == NIL or r == NIL return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l.val != r.val return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return isSymmetric(l.left, r.right) and
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> isSymmetric(l.right, r.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>寫成Java如下，注意我們這邊將isSymmetric函式的前2行合併了，&lt;br>
使用者也可以依自己習慣決定要不要這麼寫，速度上並不會有明顯差異。&lt;br>
同時，對Java而言，我們可以定義同名的函式，只要輸入的參數(parameter)型態或數量不同，JVM就可以知道哪一條式子是呼叫哪一個函式才正確。&lt;br>
這個做法稱為&lt;strong>函式多載(Method Overloading)&lt;/strong> 。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9e4954ddb7cba07364e1265d80e3ae98.js">&lt;/script>
&lt;p>Python並不支援函式多載，所以我們可以定義不同的名字來使用。&lt;br>
(註: 對於所有程式語言來說，&lt;br>
代表&amp;quot;&lt;strong>且&lt;/strong> &amp;ldquo;的操作，只要第一個條件為&lt;strong>假&lt;/strong> ，後面就不會再進行判斷；&lt;br>
代表&amp;rdquo;&lt;strong>或&lt;/strong> &amp;ldquo;的操作，只要第一個條件為&lt;strong>真&lt;/strong> ，後面也不會再進行判斷。&lt;br>
這個特性是為了節省時間，因為&lt;strong>結果已經確定了&lt;/strong> 。&lt;br>
讀者可以留意一下這點，&lt;br>
避免將一些希望一定要被執行的函式放在判斷條件的第二個以後，&lt;br>
以免發生預期要做的事情結果沒做的狀況。)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/66937a7afdf124a04fdc95310a33faf3.js">&lt;/script>
&lt;p>上面是遞迴的部分，接下來我們改成嘗試來使用迭代法解看看。&lt;br>
這邊首先要介紹一個資料結構Queue(隊列/佇列)。&lt;br>
隊列基本上就跟現場排隊名店一樣，扣除掉一些現實中的插隊之類的糟糕狀況外，基本上是&lt;strong>先排隊的可以先離開排隊序列而進場，也就是說它的特性是先進先出(FIFO)。&lt;/strong> 我們將放一個東西到Queue中的操作叫作&amp;rdquo;&lt;strong>Offer&lt;/strong> &amp;ldquo;(提供)，會放到隊列尾端；&lt;br>
從Queue裡面拿一個東西出來的操作叫作&amp;rdquo;&lt;strong>Poll&lt;/strong> &amp;ldquo;(獲得)，會從隊列頭拿出。&lt;/p>
&lt;p>這樣的特性對於解這題有什麼幫助呢？&lt;br>
我們可以如下操作：&lt;/p>
&lt;ol>
&lt;li>首先判斷root的部分，沒有問題的話拿出其左右(l跟r)，放到Queue裡面。&lt;/li>
&lt;li>此時Queue裡面有東西，一次拿兩個出來(poll兩次)，判斷l跟r本身&lt;br>
(如同遞迴時一樣)&lt;/li>
&lt;li>接下來我們應該要判斷的是&lt;strong>l.left, r.right跟l.right, r.left&lt;/strong> ，&lt;br>
所以我們將這四個節點依序offer至Queue中。&lt;/li>
&lt;li>重複2~3的動作直到&lt;strong>Queue空掉&lt;/strong> 或當中&lt;strong>判斷為假&lt;/strong> 的狀況即回傳&lt;strong>假&lt;/strong> 。&lt;/li>
&lt;li>如果Queue空掉了才離開循環，代表結果為&lt;strong>真&lt;/strong> ，回傳&lt;strong>真&lt;/strong> 值。&lt;/li>
&lt;/ol>
&lt;p>這裡我們利用了Queue的特性，只要依照我們目標的順序將東西放進Queue，我們就可以一直按照正確的方式拿到2個需要被判斷的節點。&lt;br>
這邊要注意一點，&lt;strong>如果兩個節點均為NIL，只代表這個部分往下沒有節點了，不能直接回傳真值&lt;/strong> (因為其他部分還沒比較完)，只是我們在這個位置不需要再放節點進到Queue中而已。&lt;/p>
&lt;p>寫成虛擬碼如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 8
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"> 9
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">10
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">11
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">12
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">13
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">14
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">15
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">16
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">17
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>isSymmetric(root) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> create a queue named q
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if root == NIL return true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(root.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(root.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> while q is not empty {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> l = q.poll()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> r = q.poll()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l == NIL and r == NIL continue
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l == NIL or r == NIL return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> if l.val != r.val return false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(l.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(r.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(l.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> q.offer(r.left)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> return true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>注意&lt;strong>continue&lt;/strong> 是用來表示這輪的迴圈不再繼續，直接跳到下一輪。&lt;/p>
&lt;p>Java的&lt;strong>LinkedList&lt;/strong> 已經有實作包含Queue的資料結構了，所以我們定義一個Queue時，實際上可以使用LinkedList作為宣告的物件。&lt;/p>
&lt;h3 id="java-1">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/d09cb49e5bf2cedd1d32fc656262eb6a.js">&lt;/script>
&lt;p>Python的部分，由於list的特性和Queue不太一致，&lt;br>
從&lt;strong>開頭取出&lt;/strong> 這點會讓用list模擬Queue的行為消耗大量的時間。&lt;br>
針對這點，Python有提供一個&lt;strong>deque&lt;/strong> 的物件可以使用，取出請用&lt;strong>popleft()&lt;/strong> ，放入請用&lt;strong>append()&lt;/strong> 即可。除了像Java這樣子的寫法以外，我們也可以將其使用list的形式每兩個作為一個單位來操作，請參閱下面的程式碼。&lt;/p>
&lt;h3 id="python-1">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/549435d4df430227c40e6f734dea4f36.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(最糟的狀況均為O(N)，因為要查完所有資料有可能要塞完全部的node&lt;br>
遞迴的狀況如果該樹是平衡的話，空間複雜度可以降到O(logN))&lt;/p>
&lt;p>「可以將左右比較的順序調過來嗎？」&lt;br>
(只要對應的節點是正確的，先比左邊還是先比右邊並無差異)&lt;/p>
&lt;p>「如果我不想在前面單獨判斷root的話，有可能嗎？」&lt;br>
(去掉第4行，並將第一次offer的(root.left, root.right)改成(root, root)即可。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 13 Tree (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/</link><pubDate>Mon, 15 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 13 Tree (1)" />&lt;p>&lt;strong>0100. Same Tree (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two binary trees, write a function to check if they are the same or not.&lt;/p>
&lt;p>Two binary trees are considered the same if they are structurally identical and the nodes have the same value.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 3 2 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> [1,2,3], [1,2,3]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: true
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> [1,2], [1,null,2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / \ / \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2 1 1 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span> [1,2,1], [1,1,2]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Output: false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定兩個二元樹，試寫出一個函式來檢查二者是否相等。&lt;br>
(相等的定義是指樹的結構相同，且其相同位置節點的值也相等)&lt;/p>
&lt;p>到了第13篇，終於來到樹的部分了，想當年大學時在演算法的課上被各種資料結構搞得眼花撩亂，當中二元樹/二元搜尋樹真的只能算小兒科XD&lt;br>
(不信？有心更進階的讀者可以試試看了解一下&lt;a class="link" href="https://en.wikipedia.org/wiki/Red%e2%80%93black_tree" target="_blank" rel="noopener"
>紅黑樹&lt;/a>)&lt;/p>
&lt;p>扯遠了，我們回頭來談樹。&lt;br>
在程式的領域中，樹是指資料之間以一種長得像樹的方式連結在一起的資料結構(廢話XD)，以外型而言就像&lt;strong>樹狀圖&lt;/strong> 或&lt;strong>族譜&lt;/strong> 那樣子，不過它們有一點比較特別，那就是他們的&lt;strong>根通常是畫在上方&lt;/strong> ，下面才是支幹。&lt;br>
如下圖我們所看到的：&lt;/p>
&lt;ol>
&lt;li>每個圈圈我們稱之為&lt;strong>節點(node)&lt;/strong> 。2.最上面的節點是整棵樹的起始，所以我們就稱之為&lt;strong>根(root)&lt;/strong> 。3. 就如族譜一樣，上面節點是下面直接連接的父母，&lt;br>
所以我們稱如&lt;strong>A是B和C的父節點(parent)&lt;/strong> (不要問我為什麼不叫母節點XD)，而&lt;strong>B和C是A的子節點(child)，&lt;/strong> 同時&lt;strong>B和C是兄弟節點(siblings)&lt;/strong> 。&lt;/li>
&lt;li>任何從自身追尋血脈上去可以到達的節點均為你的&lt;strong>祖先(ancestor)&lt;/strong> 。&lt;br>
比如A是所有人的祖先，而B不是G的祖先。&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-001.png"
width="731"
height="688"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-001_hu9b36bc4309e814cc748d8f9deb5cfbcd_36053_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-001_hu9b36bc4309e814cc748d8f9deb5cfbcd_36053_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="255px"
>&lt;/p>
&lt;p>From Wikipedia: Tree&lt;/p>
&lt;p>樹本身並沒有規定一個節點要連接多少個節點或總共有多少個節點，&lt;br>
你可以子孫滿堂開枝散葉，也可以孑然一身孤苦伶仃，只要有一個根在，&lt;br>
就可以被稱做一棵樹。&lt;/p>
&lt;p>不過這邊要介紹的是&lt;strong>二元樹(binary tree)&lt;/strong> ，就有比較明確的限制了，&lt;br>
每個節點最多只能有&lt;strong>2&lt;/strong> 個分支。且&lt;strong>左右分支是視作不同&lt;/strong> 的，將它們互相交換的話，前後兩個二元樹會被視為不同的二元樹。由於只有2個分支，所以一個節點的兩個子節點又可以分別被叫做左節點和右節點(left/right node)，&lt;br>
單就這兩個節點來看，都可以各自視為一個二元樹，&lt;br>
同樣依照左右被稱作&lt;strong>左子樹/右子樹(left/right subtree)&lt;/strong> 。&lt;br>
後續還有一個規範更嚴格，也更常被用到的二元樹稱為&lt;strong>二元搜尋樹(Binary Search Tree, BST)&lt;/strong> ，這個我們之後會專門再開一篇講解。上面這些均為樹的相當基本的部分，並不困難，還請詳加閱讀後再往下。&lt;/p>
&lt;p>如同先前提過的linked list一樣，當一個節點它有一邊沒有連接，或者是已經沒有子節點的時候，嚴謹的資料結構會將其連接至&lt;strong>NIL&lt;/strong> (表示什麼都沒有)，而在&lt;strong>Java中用null，Python則用None&lt;/strong> 表示。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-002.png"
width="547"
height="315"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-002_huc459cfa54f19a80c29671b3e46aa84b6_14296_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-002_huc459cfa54f19a80c29671b3e46aa84b6_14296_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="173"
data-flex-basis="416px"
>&lt;/p>
&lt;p>一個Binary Tree, 15的左邊/17, 23, 25的左右其實都是NIL(恩，其實它也是BST)&lt;/p>
&lt;p>回到問題，其實問題的輸入是透過array或list的型式，但這邊LeetCode應該已經妥善處理好建造二元樹的過程了，我們暫且不管它。&lt;br>
我們如何判斷兩個二元樹是否相等呢？&lt;br>
由於相等的前提是&lt;strong>結構相同且所有對應的節點的值&lt;/strong> 也相同，我們勢必要一個一個檢查才能知道結果，所以我們必須要&lt;strong>走訪整棵樹(Tree Traversal&lt;/strong> )。&lt;br>
一個標準的走訪分成四種模式：&lt;br>
&lt;strong>前序、中序、後序以及層序(Pre-order/In-order/Post-order/Level-order)&lt;/strong> 我們這次只會先從最直覺的前序遍歷開始。&lt;/p>
&lt;p>假設如題目所提，我們有兩棵二元樹，他們的root分別是p跟q，&lt;br>
那麼檢查它們是否相等的話，我們要做的事情是：&lt;/p>
&lt;ol>
&lt;li>檢查&lt;strong>p和q是否相等&lt;/strong>&lt;/li>
&lt;li>檢查&lt;strong>p的左子樹&lt;/strong> 和&lt;strong>q的左子樹&lt;/strong> 是否相等&lt;/li>
&lt;li>檢查&lt;strong>p的右子樹&lt;/strong> 和&lt;strong>q的右子樹&lt;/strong> 是否相等&lt;br>
唯有這三項均成立，我們才能說p跟q兩棵二元樹相等，否則即為不相等。&lt;br>
接下來，我們先考慮2和3的部分，&lt;br>
其實就等同於&lt;strong>反複拿更小的子樹去做1~3的動作，&lt;br>
直到比對的兩邊當中有不同或空掉的狀況&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>我們拿下面的圖為例，可以簡單推論出，&lt;br>
當&lt;strong>檢查兩個節點是否相等&lt;/strong> 的狀況有幾個可確定：&lt;br>
a. 一邊有節點，另一邊沒有節點 =&amp;gt; 結構已經不一樣了，所以&lt;strong>兩棵樹不同&lt;/strong> 。&lt;br>
b. 兩邊均無節點 =&amp;gt; &lt;strong>結構相同&lt;/strong> 且沒有子節點，所以&lt;strong>這個位置的子樹相同&lt;/strong> 。&lt;br>
c. 兩邊都有結點 =&amp;gt; &lt;strong>檢查值是否相同，相同的話，再檢查左右子樹&lt;/strong> 。&lt;br>
(也就是回到上一段那邊的2~3)&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-003.png"
width="400"
height="155"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-003_hu6141e23f1a9be1c80266a1df110a17ce_6282_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-003_hu6141e23f1a9be1c80266a1df110a17ce_6282_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="258"
data-flex-basis="619px"
>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-004.png"
width="400"
height="155"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-004_hu6ad152cbcd35ec3b785f7763d5feea7a_7973_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-13-tree-1/image-004_hu6ad152cbcd35ec3b785f7763d5feea7a_7973_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="258"
data-flex-basis="619px"
>&lt;/p>
&lt;p>所以，我們可以用連續呼叫自己這個解題函式的方式來解決這個問題，&lt;br>
其演算方式可以大致列成這樣：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>isSameTree(p, q) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 若p和q均為NIL，回傳真
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 若p或q為NIL，回傳假(因為表示恰有一個是NIL)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 回傳 (p.val==q.val) 且 isSameTree(p.left, q.left) 且 isSameTree(p.right, q.right)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>注意這樣子的比較，我們每次是&lt;strong>先比較根節點&lt;/strong> ，再比較&lt;strong>左節點&lt;/strong> 的部分，最後才是比較&lt;strong>右節點&lt;/strong> ，同時，每次呼叫isSameTree時，會一路往左邊先找下去，直到左子樹找完了才會走訪右子樹的部分，所以順序是&lt;strong>根-左-右&lt;/strong> ，也就是一般所謂的前序遍歷(Pre-order Traversal)。&lt;/p>
&lt;p>這種不斷呼叫自己來求解的方式，我們稱之為&lt;strong>遞迴(Recursion，或譯遞歸)&lt;/strong> ，這樣的解法一般稱為&lt;strong>遞迴解(Recursive solution)&lt;/strong> ，一般來說還會有另一種解法，主要是透過&lt;strong>額外的資料結構及迴圈&lt;/strong> ，來解決問題，這種方式叫做&lt;strong>迭代法/迭代解(Iterative method/Iterative solution)&lt;/strong> 。比較熟練的讀者若有興趣，可以自行嘗試使用Queue或Deque來解本題看看。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/0d35a8d31b8370b5b726a420b09f376f.js">&lt;/script>
&lt;p>Python的部分，由於NIL是用None來表示，&lt;br>
所以檢查可以用if not的方法來處理，且&lt;strong>not運算的優先層級高於and/or&lt;/strong> ，&lt;br>
所以我們不用額外幫它加括號。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/47039932c601895037c316bc7bec1842.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間複雜度/空間複雜度？」&lt;br>
(如果答案為真的話，那麼&lt;strong>每個節點均會走訪一次，故為O(N)&lt;/strong> )&lt;br>
(空間複雜度的話，遞迴同樣會佔用記憶體空間，層數則取決於樹的層數，&lt;br>
如果是平衡樹(balanced tree)的話，因為分布要平衡(填滿)，&lt;br>
每層的節點數量會是1, 2, 4, 8, 16, &amp;hellip;, 總和N=2的n次方-1，n為層數。&lt;br>
所以空間複雜度會是&lt;strong>O(logN)&lt;/strong> ，N為節點的總數。&lt;br>
最差的狀況下，節點全部連在同一邊，那空間複雜度可以達到O(N)。)&lt;/p>
&lt;p>「可以不用遞迴解嗎？」&lt;br>
(可以，有興趣的讀者可以嘗試看看，具體方式是使用Queue或Deque，先將兩個根節點放入，接著每次取出一組節點對；先比較節點，&lt;strong>再將兩樹其左右node成對地放入裡面&lt;/strong> ，重複迴圈，直到有&lt;strong>不相等&lt;/strong> 的狀況產生，或直到&lt;strong>Queue/Deque內再無節點&lt;/strong> 。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 12 Linked List (3)/ Stack (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-12-linked-list-3-stack-1/</link><pubDate>Fri, 12 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-12-linked-list-3-stack-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 12 Linked List (3)/ Stack (1)" />&lt;p>&lt;strong>0092. Reverse Linked List II (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Reverse a linked list from position &lt;em>m&lt;/em> to &lt;em>n&lt;/em>. Do it in one-pass.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> 1 ≤ &lt;em>m&lt;/em> ≤ &lt;em>n&lt;/em> ≤ length of the list.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;5-&amp;gt;NULL, m = 2, n = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;4-&amp;gt;3-&amp;gt;2-&amp;gt;5-&amp;gt;NULL
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個linked list，在只經過一次的操作下(每個node不會額外再走訪)，&lt;br>
題目要求將m到n的位置的節點進行反轉。&lt;/p>
&lt;p>由範例可知這邊的m跟n是以開頭為1而非0來計算，這點讀者請特別留意。&lt;/p>
&lt;p>我們先從理論上來看這題應該怎麼處理：&lt;br>
首先根據題目要求，m可能和n相等，&lt;br>
相等的狀況下其實完全不用做事，回傳head即可。&lt;/p>
&lt;p>那麼如果是不相等的狀況呢？&lt;br>
在Linked List中，要知道某個位置的節點為何，唯有&lt;strong>從頭一路走到該節點&lt;/strong> 。&lt;br>
我們想要反轉的是m&lt;del>n的位置：&lt;br>
以範例來說，會將2&lt;/del>4的位置進行反轉。&lt;br>
如何反轉呢？首先我們要先走到2的左邊，當我們把中間的部分反轉後，&lt;br>
我們還要將它們和左右兩邊接起來，要記得2的左邊跟4的右邊的節點才行。&lt;br>
(不然接不起來就GG了XD)&lt;br>
這邊將2的左邊命名為left，一路往下走的迭代節點命名為node，&lt;br>
走到m-1以前先記錄下left節點，再繼續往下走。&lt;/p>
&lt;p>接下來問題來了，如何將2~4的部分反向連接呢？&lt;br>
你可以選擇一個一個拆解並重新鍵結，&lt;br>
但這裡筆者想介紹一個常用的資料結構：Stack(堆疊，或稱棧/堆棧)。&lt;br>
Stack的樣子，就跟某些苦命的辦公室人員的書桌一樣：&lt;br>
&lt;strong>你會嘗試將書桌上的文件/工作處理完，但老闆總是會往上面再加新的。&lt;/strong> 也就是說，每次如果你選擇&lt;strong>從最上面開始拿&lt;/strong> (別從中間或下面，這麼高的文件可是會塌的！)，你會拿到&lt;strong>最新的&lt;/strong> 工作。&lt;/p>
&lt;p>Stack也是如此，假設你將1, 2, 3, 4, 5依序放入Stack中，那麼當你從Stack裡面拿東西的時候，拿出來的順序會是5, 4, 3, 2, 1。&lt;strong>最後放進去的會最先被拿出來&lt;/strong> ，這樣子的特性我們稱之為Last In First Out(後進先出，簡寫為LIFO)。有另一種資料結構叫&lt;strong>Queue(隊列，或稱佇列)&lt;/strong> 跟它剛好相反，是&lt;strong>先進先出&lt;/strong> ，我們以後找機會再講解它。&lt;/p>
&lt;p>如果這題應用上Stack的話，就簡單許多：&lt;br>
&lt;strong>我們將2~4的部分通通丟進Stack中，再一個一個拿出來&lt;/strong> ，&lt;br>
這時候順序就會變成4, 3, 2了！那麼，只要將剛剛存好的left，以及後面我們邊走邊看到4的時候，將它的右邊記錄起來的node，兩者再和中間的節點連結起來，就完成整個反轉的流程。&lt;/p>
&lt;p>重新整理解題的順序：&lt;/p>
&lt;ol>
&lt;li>判斷m是否和n相等，相等則直接回傳原先的head。&lt;/li>
&lt;li>定義一個迭代用節點node，先走到m-1的位置以取得節點left。&lt;/li>
&lt;li>讓node從m一路走到n，將每個node放入到Stack中。&lt;br>
(註:放入的術語在堆疊中叫作push)&lt;/li>
&lt;li>node再額外走一步會走到n+1的位置&lt;/li>
&lt;li>依次將Stack中的節點取出，並且依序連接所有節點的next，&lt;br>
直到Stack中再也沒有節點。&lt;br>
(註:取出的術語在堆疊中叫做pop)&lt;/li>
&lt;li>將反轉完的尾巴和node做連接，結束整個反轉的流程。&lt;/li>
&lt;/ol>
&lt;p>這當中還有額外一點需要注意的是&lt;strong>m=1&lt;/strong> 的狀況，&lt;br>
因為我們最後回傳的是用&lt;strong>head&lt;/strong> 來代表整個linked list，&lt;br>
如果m為1的話，代表head其實已經被改變了，&lt;br>
我們需要同步更新head的部分。&lt;/p>
&lt;p>請參照Java的寫法，我們採用了l1和l2兩個節點來處理依序連接的部分。&lt;br>
我們會先取出堆疊中第一個節點，這個節點會被left連接，&lt;br>
接下來使用&lt;strong>l2 = st.pop(); l1.next=l2; l1 = l2;&lt;/strong>&lt;br>
來進行一次取一個node，將前後連接好以後，&lt;br>
將位置移到下一個準備連接的點。&lt;br>
也就是說，&lt;strong>每次l1所在的位置，都是當前準備進行連接next的節點&lt;/strong> 。&lt;br>
(若讀者對這邊的說明感到抽象，請務必在紙上試著操作一下會較清楚)&lt;/p>
&lt;p>在Java中，Stack的宣告方式是：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Stack&amp;lt;&amp;gt; st = new Stack&amp;lt;&amp;gt;();
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>請在&amp;quot;&amp;lt;&amp;gt;&amp;ldquo;之中填入你想要使用的資料型態，&lt;br>
在本例中為題目已經定義的class ListNode。&lt;/p>
&lt;p>函式用法的部分，push()用來放入節點，pop()用來取出節點，&lt;br>
isEmpty()則是檢查Stack是否是空的。&lt;br>
(還有一個peek()，是用來看Stack最上面節點，&lt;br>
但不會真的將節點從Stack中移除)&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/5f1c1300afeb8aa6ab4cfabebbb09f28.js">&lt;/script>
&lt;p>在Python中，list的特性可以方便的用來當作Stack使用，&lt;br>
放入節點可以使用append()，取出節點使用pop()。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/eeb85ba29bb9832ce6143040c9a799be.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(n-m)，因為我們的堆疊最多只需要存中間的部分和兩旁的node)&lt;/p>
&lt;p>「可以只用O(1)的空間嗎？」&lt;br>
(可以，如果我們按順序一個一個處理m~n之間的連結，&lt;br>
最後再將n和m和左右兩邊連起來，是可以不使用Stack的&lt;br>
中間的連接方式會像是：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>third = cur.next
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cur.next = prev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>prev = cur
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cur = third
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>讀者有興趣的話可以嘗試看看。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 11 Bitwise Operation (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-11-bitwise-operation-1/</link><pubDate>Thu, 11 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-11-bitwise-operation-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 11 Bitwise Operation (1)" />&lt;p>&lt;strong>0089. Gray Code (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>The gray code is a binary numeral system where two successive values differ in only one bit.&lt;/p>
&lt;p>Given a non-negative integer &lt;em>n&lt;/em> representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [0,1,3,2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>00 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>01 - 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11 - 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>10 - 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>For a given n, a gray code sequence may not be uniquely defined.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>For example, [0,2,3,1] is also a valid gray code sequence.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>00 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>10 - 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11 - 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>01 - 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: [0]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: We define the gray code sequence to begin with 0.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> A gray code sequence of n has size = 2n, which for n = 0 the size is 20 = 1.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Therefore, for n = 0 the gray code sequence is [0].
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>格雷碼是一個二進位表示的編碼系統，當中每個連續(相鄰)的二個值之間的表示方式只會相差一個位元(bit)。題目給定n個bits，試求出其表達的格雷碼序列。(格雷碼序列一定是從0開始)&lt;/p>
&lt;p>在這邊簡單講解一下Bitwise Operation。&lt;br>
(註:本題雖然不會用到太多，&lt;br>
但熟悉這些操作對於一些題目和實際應用上很有幫助，&lt;br>
故在此先行列出給讀者學習。)&lt;/p>
&lt;p>先前的文章中已經提到了，電腦對於二進位制的東西操作起來是較為得心應手的，當然我們可以不用像電腦這麼熟悉，但只要會用就可以了XD&lt;br>
二進位之間的一些操作運算，就像是邏輯學上的運算一樣，&lt;br>
有AND/OR/NOT/XOR，以及位移運算(bit shifts)等，這些速度在相同狀況下是由CPU進行支援的，運算速度往往會比一般的四則運算還快。&lt;/p>
&lt;p>&lt;strong>AND(且):&lt;/strong>&lt;br>
邏輯上的AND，代表著&lt;strong>前後皆為真的狀況結果才為真，否則為假&lt;/strong> ，&lt;br>
也就是兩者皆成立才行。在位元運算中，1被視為真，0被視為假。&lt;br>
(所以在如C/C++中你可能會看到使用IF 1或IF 0的開關)&lt;br>
延伸到多個bit的狀況，就是將前後兩者每個bit兩兩相對，&lt;br>
當兩者為1時，運算完的那個新的bit為1，否則為0。&lt;br>
如 110 AND 100的結果會是100(只有最左邊的bit是兩個1)&lt;br>
&lt;strong>Java和Python中的AND運算符號均為&amp;quot;&amp;amp;&amp;quot;&lt;/strong> 。&lt;br>
(請留意，如果判斷兩個&lt;strong>運算結果的是否為真&lt;/strong> 的邏輯運算，&lt;br>
&lt;strong>Java是&amp;quot;&amp;amp;&amp;amp;&amp;quot;，Python則是&amp;quot;and&amp;quot;&lt;/strong> ，&lt;br>
以位元為基準的運算和求真偽的邏輯運算是不同的，記得不要搞混了！)&lt;/p>
&lt;p>&lt;strong>OR(或):&lt;/strong>&lt;br>
前後兩者只要其一為真結果即為真，&lt;br>
也就是&lt;strong>只有兩者皆不成立時，結果才會是假&lt;/strong> 。&lt;br>
所以在位元運算中，&lt;br>
兩兩相對，&lt;strong>除了兩個bit都是0的運算結果是0外，其餘都會是1&lt;/strong> 。&lt;br>
如 110 OR 100的結果會是110(只有最右邊的bit是兩個0)&lt;br>
&lt;strong>Java和Python中的OR運算符號均為&amp;quot;|&amp;quot;&lt;/strong> 。&lt;br>
(如果是邏輯運算的話，&lt;strong>Java是&amp;quot;||&amp;quot;，Python則是&amp;quot;or&amp;quot;&lt;/strong> )&lt;/p>
&lt;p>&lt;strong>NOT(非):&lt;/strong>&lt;br>
邏輯上的NOT，代表將該真/假狀況轉為&lt;strong>原先的相反&lt;/strong> ，&lt;br>
&lt;strong>真的變假的，假的變真的&lt;/strong> 。&lt;br>
在位元運算中，對每個bit操作，&lt;br>
&lt;strong>只要原先是1的均變為0，為先為0的則變為1&lt;/strong> 。&lt;br>
如NOT 110的結果會是001。&lt;br>
&lt;strong>Java和Python中NOT運算符號均為&amp;quot;~&amp;quot;&lt;/strong> 。&lt;br>
(如果是邏輯運算的話，&lt;strong>Java是&amp;quot;!&amp;quot;，Python則是&amp;quot;not&amp;quot;&lt;/strong> )&lt;/p>
&lt;p>&lt;strong>XOR(互斥或，Exclusive OR):&lt;/strong>&lt;br>
邏輯上的XOR，代表&lt;strong>前後兩個狀況剛好有一個成立時為真&lt;/strong> ，&lt;br>
即前真後假/前假後真，其餘皆為假。&lt;br>
位元運算的部分，兩兩相對檢查，當發現是一個1一個0的時候，&lt;br>
結果為1，否則均為0。&lt;br>
如1100 XOR 1010的結果會是0110。&lt;br>
&lt;strong>Java和Python中的XOR運算符號均為&amp;quot;^&amp;quot;&lt;/strong> 。&lt;/p>
&lt;p>&lt;strong>位移運算:&lt;/strong>&lt;br>
將一個數的所有bit的東西往左或往右移動指定的位元數，&lt;br>
超出儲存空間的部分捨棄，被位移走的原處則補0。&lt;br>
&lt;strong>Java和Python中使用&amp;quot;&amp;laquo;&amp;ldquo;和&amp;rdquo;&amp;raquo;&amp;ldquo;分別代表向左位移及向右位移。&lt;/strong>&lt;br>
例如:&lt;br>
 2 &amp;laquo; 1 的結果會是4，因為2的二進位是&amp;quot;10&amp;rdquo;，&lt;br>
這個操作代表2向左位移1個bit，空白的部分補零，&lt;br>
所以會得到&amp;quot;100&amp;quot;也就是十進位制的4。&lt;/p>
&lt;p>9 &amp;raquo; 2的結果會是2，因為9的二進位是&amp;quot;1001&amp;quot;，&lt;br>
這個操作代表向右位移2個bit，所以&amp;quot;01&amp;quot;的部分移出儲存範圍了被捨棄掉，&lt;br>
會得到&amp;quot;10&amp;quot;，也就是十進位的2。&lt;/p>
&lt;p>直觀上我們可以將位移N個bit視作乘以或除以2的N次方，&lt;br>
但要注意範圍是否正確，以及是否要&lt;strong>處理正負號&lt;/strong> 的部分。&lt;/p>
&lt;p>上面介紹了位元運算以後，讓我們回到題目。&lt;br>
在通訊傳輸的過程中，有可能因為受到雜訊干擾等狀況，&lt;br>
使得當中的位元反轉(0變成1，1變成0)。倘若我們按照正常的表達方式，&lt;br>
例如7=0111, 8=1000，對於某些臨界狀況而言，小範圍的變動值會需要大幅度的修改bit，同時當某個高位數的bit出錯的狀況，值就有可能受到大幅度的改變，這顯然是比較糟糕的。&lt;/p>
&lt;p>所以格雷碼的設計就是希望能夠讓更動小數值的時候，只更動較少的bit數量即可，且當有其中的bit受到干擾而出錯時，數值的影響範圍也較小。&lt;/p>
&lt;p>那怎麼計算呢？&lt;br>
我們從1個bit開始推導看看：&lt;br>
由於要求要從0開始，&lt;br>
故我們應該是拿0代表0，1代表1，這樣就完成了1個bit的格雷碼。&lt;br>
2個bit的話，由於用10來表示會一次更動2個bit(01-&amp;gt;10)，&lt;br>
所以我們只能拿11來表示2，而10則表示3。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>00 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>01 - 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11 - 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>10 - 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當然，也可以用00, 10, 11, 01來進行表示，但這種方式相對較複雜，&lt;br>
我們直接去考慮前面的方式的邏輯就好。&lt;/p>
&lt;p>再來我們可以思考，在不要動到前面的數的狀況下，&lt;br>
下面我們要怎麼表達3個bit的狀況呢？&lt;br>
已經知道：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>000 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>001 - 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>011 - 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>010 - 3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>我們想要剛好用3個bit表示0&lt;del>7，&lt;br>
那唯有讓4&lt;/del>7的部分的最左邊的bit均為1才行。&lt;br>
(因為前面的2個bit組合已經被用過了)&lt;br>
同時我們又想要符合&lt;strong>相鄰只動一個bit&lt;/strong> 的原則，&lt;br>
所以4的表示方式就只剩下110了!&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>000 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>001 - 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>011 - 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>010 - 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>110 - 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1xx - 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1xx - 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1xx - 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>同時，我們也知道前面0&lt;del>3符合這個只動一個bit的表達方式，&lt;br>
那麼後面填入5&lt;/del>7的方式，就可以按照&lt;strong>上下鏡向&lt;/strong> 的狀況填入，&lt;br>
自然會符合格雷碼的要求。也就是除了最左邊是1以外，&lt;br>
4對應到3，5就對應到2，6對應到1，7對應到0即可。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>000 - 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>001 - 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>011 - 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>010 - 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>110 - 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>111 - 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>101 - 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>100 - 7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>同樣的道理，變成4個bit時，將後面的8個數的最左邊的bit填入1，&lt;br>
其它的部分鏡向填入即可。&lt;/p>
&lt;p>歸納一下這題的解法：&lt;/p>
&lt;ol>
&lt;li>先放入0(最開始的部分，也是n=0時的解答)&lt;/li>
&lt;li>定義一個變數adder，用來表示這輪要加上去的bit所代表的值&lt;br>
(初始值是2的0次方=1)&lt;/li>
&lt;li>每次將答案的尾端加上一個新的值，&lt;br>
這個新的值是鏡向對應到的值加上adder。&lt;br>
(鏡向對應的方式，可以從尾端開始往回算，或者用adder-1-index來計算)&lt;/li>
&lt;li>計算完畢一輪以後，將adder變為2倍，作為下一輪要額外加上去的值。&lt;/li>
&lt;li>一路操作直到完成n輪為止，最後將結果回傳。&lt;/li>
&lt;/ol>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/eca8cea11c9b42f8b4d63891a214e54a.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/9183373eb4afe383040d4ae9d2ccd1a2.js">&lt;/script>
&lt;p>讀者可以看到兩個解法中一個使用+adder，另一個使用|add，&lt;br>
結果上是一樣的，因為加上去的那個bit一定是跟0相加，&lt;br>
故可以用OR運算會加快一點速度。(讀者可以修改成+來比較看看速度)&lt;br>
*2和&amp;laquo;=1的部分，同樣可以等價於位移一個bit，&lt;br>
但速度上應該不會有特別差異才對。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間複雜度？」&lt;br>
(O(2的n次方)，因為n個bit可以表示2的n次方個數)&lt;/p>
&lt;p>「(Python)能不能不要用append來解？」&lt;br>
(可以用extend，&lt;br>
每次將res的部分反轉接上後，再進行add的加總)&lt;/p>
&lt;p>「為什麼你要用&amp;quot;_&amp;quot;？」&lt;br>
(因為第一個迴圈事實上只是處理執行n次這件事情，&lt;br>
我們並不需要用到其數值，在習慣上會盡量用底線來命名，&lt;br>
避免去用到有意義的命名方式。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 10 Linked List (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-10-linked-list-2/</link><pubDate>Wed, 10 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-10-linked-list-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 10 Linked List (2)" />&lt;p>&lt;strong>0083. Remove Duplicates from Sorted List (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a sorted linked list, delete all duplicates such that each element appears only &lt;em>once&lt;/em>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;1-&amp;gt;2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;1-&amp;gt;2-&amp;gt;3-&amp;gt;3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;2-&amp;gt;3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個已排序好的linked list，要求將所有重複的node皆刪除，&lt;br>
使得每個元素均只出現一次。&lt;/p>
&lt;p>這題也算是比較簡單的linked list類型，只要確定連接正確的話並不難解。&lt;br>
由於已經排序過的原因，所有會重複的元素值均會相鄰，那麼我們所要做的就是遇到重複時&lt;strong>總共只保留一個就好了&lt;/strong> 。&lt;br>
保留哪一個呢？當然是保留第一個囉！&lt;/p>
&lt;p>我們可以先宣告一個ListNode，命名為ite用來做為iterator(迭代器)，&lt;br>
每次取得ite的下一個node(命名為tmp)做為暫存。&lt;br>
接下來開始一路往下尋找，如果ite和tmp前後值相等時，就讓tmp開始往下&lt;strong>一直走到底部(表示後面值都一樣)&lt;/strong> 或者&lt;strong>找到下一個不同的值。&lt;/strong> 對於&lt;strong>前者的狀況&lt;/strong> 而言，表示結束，tmp會指到null(或None)，&lt;br>
只要將&lt;strong>ite.next指向到tmp&lt;/strong> 即可。&lt;/p>
&lt;p>對於&lt;strong>後者的狀況&lt;/strong> ，這時候tmp的位置就在&lt;strong>下一個相異值的點&lt;/strong> 。&lt;br>
像是1-&amp;gt;2-&amp;gt;2-&amp;gt;2-&amp;gt;3-&amp;gt;4這樣子，從ite在碰到第一個2以後，&lt;br>
tmp會一路找到3的位置，所以我們只要將&lt;strong>ite.next指向到tmp&lt;/strong> ，&lt;br>
即可將第一個2接到3的位置，從而中間的部分就等於被我們刪去了。&lt;/p>
&lt;p>討論完兩者狀況後，我們會發現無論是哪一種，&lt;br>
結果都會是將ite.next指向到tmp，&lt;br>
最後要記得ite本身要遞移到下一個開始找的位置，&lt;br>
所以我們還需要將tmp的位置交給ite。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/55fea85d03d195ae3ff6a2d7e5500524.js">&lt;/script>
&lt;p>以Python的部分來說，還記得判斷式可以直接適用於if的話，&lt;br>
就可以寫得看起來簡潔一些。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/aab3f6eec5e1901867f93ac138364f1c.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1))&lt;/p>
&lt;p>其它應該沒什麼好問的，至少我沒想到XD&lt;br>
這篇主要是協助讀者再熟悉一下這些連接/斷開的操作。&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 9 Dynamic Programming (2)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-9-dynamic-programming-2/</link><pubDate>Tue, 09 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-9-dynamic-programming-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 9 Dynamic Programming (2)" />&lt;p>&lt;strong>0070. Climbing Stairs (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>You are climbing a staircase. It takes &lt;em>n&lt;/em> steps to reach to the top.&lt;/p>
&lt;p>Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong> Given &lt;em>n&lt;/em> will be a positive integer.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There are two ways to climb to the top.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1. 1 step + 1 step
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2. 2 steps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There are three ways to climb to the top.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1. 1 step + 1 step + 1 step
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2. 1 step + 2 steps
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3. 2 steps + 1 step
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目描述有一個要爬n階才能到頂端的階梯，每次只能爬1階或2階，&lt;br>
試求有多少種不同的方法可以走到頂端。&lt;br>
如果以窮舉的話我們可能需要列很久，&lt;br>
所以這時候又回到了看看是否能找出相互關係的時候了。&lt;/p>
&lt;p>我們考慮要爬n階的話，首先要先爬到&lt;strong>n-1&lt;/strong> 階或&lt;strong>n-2&lt;/strong> 階，因為只有一次走1階或一次走2階的選擇。也就是說，走到n階的方法，就相當於&lt;strong>走到n-1階的方法和走到n-2階的方法和&lt;/strong> 。因為最後的步伐已經固定了，我們同時還可以保證&lt;strong>這兩個方法的組合之間不會互相重複&lt;/strong> (一個最後走1步，一個最後走2步)。&lt;/p>
&lt;p>同樣的，走到n-1階的方法=走到(n-2)階的方法+走到(n-3)階的方法，&lt;br>
以此類推拆解，最終我們來到走到第1階的方法跟走到第2階的方法，&lt;br>
分別是1跟2。&lt;/p>
&lt;p>我們可以選擇開一個res的陣列，初始化前2階以後，&lt;br>
一路加上去最終得到到第n階的方法數，下面Java的版本因為陣列由0開始，&lt;br>
有刻意將數字不先行化簡，讀者應該可以很簡單地對照。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/e6ca8d674da9778e3a36362e4c6ec032.js">&lt;/script>
&lt;p>Python的部分，則採用兩個數s1, s2來輪替使用，可以節省記憶體。&lt;br>
每次應該要做的，是將s1+s2的值擺到s2，而將s2的值擺到s1的位置。&lt;br>
(等於把兩個數代表的位置遞移了一層)&lt;br>
(Java也可以用類似的作法，但需要多宣告一個暫存值進行儲存)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/36f7e5bd29cd65347e68e9617b6c8b30.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
（O(N), 依方法而定，&lt;br>
上面Java的寫法需要O(N)，Python的寫法則只需O(1)）&lt;/p>
&lt;p>「哪個寫法比較好？」&lt;br>
(以空間節省的角度來說是Python版本的寫法較佳，&lt;br>
但如果我們不止需要算一次的話，執行一次n階，&lt;br>
其實可以將n階以下的走法數量全部記起來，&lt;br>
這樣被讀取的時候可以先查是否可以直接拿結果回傳，&lt;br>
所以反覆執行的效率會變比較好，不過這個就需要再修改一下程式就是了)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 8 String Manipulation (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-8-string-manipulation-1/</link><pubDate>Fri, 05 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-8-string-manipulation-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 8 String Manipulation (1)" />&lt;p>&lt;strong>0067. Add Binary (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given two binary strings, return their sum (also a binary string).&lt;/p>
&lt;p>The input strings are both &lt;strong>non-empty&lt;/strong> and contain only characters &lt;code>1&lt;/code> or &lt;code>0&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: a = &amp;#34;11&amp;#34;, b = &amp;#34;1&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;100&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: a = &amp;#34;1010&amp;#34;, b = &amp;#34;1011&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;10101&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定兩個二進位字串，試求其和(同樣以二進位字串表達)。&lt;br>
在電腦的世界裡，本質上是由0和1所構成的，因為對它來說，最容易的表達方式就是電路的開路和斷路兩種狀態。&lt;br>
如果大家忘記二進位的表示方式，可以從&lt;a class="link" href="https://en.wikipedia.org/wiki/Binary_number" target="_blank" rel="noopener"
>wiki的說明&lt;/a>大概回憶一下XD&lt;br>
這裡只要知道要轉為10進位的話，就是由右至左從2⁰開始相乘相加就對了。&lt;br>
例: 1010 -&amp;gt; 0*2⁰ + 1*2¹ + 0*2² + 1*2³ = 0 + 2 + 0 + 8 = 10&lt;br>
每個位數之間是2倍，每滿2就要向左邊進一位。&lt;/p>
&lt;p>那麼給定的是字串的話，要怎麼做處理呢？&lt;br>
這題很重要的一點是要先確認你是使用什麼程式語言做操作的。&lt;/p>
&lt;p>如果是C/C++/Java等規範相對嚴格的語言的話，&lt;br>
以&lt;strong>Java&lt;/strong> 為例，其int變數型態一般是用&lt;strong>32-bit&lt;/strong> 來儲存並且含有正負號，&lt;br>
也就是它只可以接受範圍在**-2³¹~2³¹-1** 之間的數字，超過這個範圍即會overflow(溢位)，這也是這個題目之所以會用字串表達的原因。&lt;br>
&lt;strong>(不同的語言的int變數所涵蓋的範圍不一定相同)&lt;/strong>&lt;/p>
&lt;p>Python就沒有這種限制，直譯器已經處理好很多事情了，&lt;br>
所以下面就會看到一些比較簡單(偷吃步)的做法。&lt;/p>
&lt;p>對Java而言，我們既然擔心會溢位導致不能夠直接轉換，&lt;br>
那麼只好一位一位去做操作了。我們可以使用StringBuilder這個處理字串的類別，從第0位開始將兩邊的數字相加，並且處理進位(carry)的部分。&lt;/p>
&lt;p>對Java而言，字串(String)拆出來的每個單位叫字元(char)，&lt;br>
使用String.charAt(i)函式，可以將index i的字元拆解出來。&lt;br>
拆出來的字元其實已經可以用數字的形態印出了，&lt;br>
但它是代表&lt;a class="link" href="https://zh.wikipedia.org/wiki/ASCII" target="_blank" rel="noopener"
>ASCII code表&lt;/a>上的位置，而非真的數字，&lt;br>
要得到它實際的數字的話，由於'0&amp;rsquo;~&amp;lsquo;9&amp;rsquo;在表上是連續的，&lt;br>
我們可以減去'0&amp;rsquo;的位置48，即可得到實際的數字；&lt;br>
或者記不了的話，&lt;strong>直接拿該字元去減掉'0&amp;rsquo;&lt;/strong> ，也可以得到相同的結果。&lt;br>
這樣的操作也適用於大小寫的英文字母上，請多留意。&lt;/p>
&lt;p>那麼問題就簡單了: 只要是還有位數的狀況下，就取出字元減掉'0&amp;rsquo;，&lt;br>
否則就當作是0(代表另一個字串比較長)，最後比到兩邊長度都用完，&lt;br>
這時候StringBuilder應該沿路將所有位數從&lt;strong>最低位組合到最高位&lt;/strong> 了，&lt;br>
最後處理最高位有可能的進位後，只要再將其進行反轉(reverse)操作，&lt;br>
再轉為字串(toString)即可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/cc6b5ff550d626da5c2a62a2949f3e9a.js">&lt;/script>
&lt;p>Python的部分相對簡單的多(可以偷吃步XD)，&lt;br>
只要將a跟b先轉成int，相加後再轉成二進位即可。&lt;br>
轉成int的作法是&lt;strong>int(num, base)&lt;/strong> ，&lt;br>
num表示你的字串，base表示這段字串的&lt;strong>進位方式&lt;/strong> 。&lt;/p>
&lt;p>相加後轉成bin要特別注意Python的表達方式是以**’0b’** 為開頭，&lt;br>
所以我們只保留index 2以後的部分。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4aa0af1b415afafdcac2e2366321e69f.js">&lt;/script>
&lt;p>簡單吧!&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間複雜度？」( O(max(len(a), len(b))) )&lt;/p>
&lt;p>「Python解是很簡單啦，但可以用一個一個比較的方法嗎？」&lt;br>
(請仿照Java的方式寫給他XD)&lt;br>
(補充: Python的ASCII和數字順序的互轉是 ord(c)跟 chr(a)，&lt;br>
前者字元轉數字，後者數字轉字元)&lt;/p>
&lt;p>「(Java)&lt;strong>j++&lt;/strong> 和**++j** 有什麼不同？」&lt;br>
(++本身是代表將這個值增加1，&lt;br>
而擺在變數後面代表&lt;strong>這整行執行完畢以後，才進行遞增&lt;/strong> ；&lt;br>
後者則代表&lt;strong>先將自己本身增加1以後，才執行這整行的操作&lt;/strong> )&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 7 Dynamic Programming (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-7-dynamic-programming-1/</link><pubDate>Thu, 04 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-7-dynamic-programming-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 7 Dynamic Programming (1)" />&lt;p>&lt;strong>0053. Maximum Subarray (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an integer array &lt;code>nums&lt;/code>, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [-2,1,-3,4,-1,2,1,-5,4],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: [4,-1,2,1] has the largest sum = 6.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Follow up:&lt;/strong>&lt;/p>
&lt;p>If you have figured out the O(&lt;em>n&lt;/em>) solution, try coding another solution using the divide and conquer approach, which is more subtle.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目給定一個整數陣列，要求找到其中一個連續的子陣列，這個子陣列的和是所有子陣列中最大的，並且回傳該總和值。&lt;/p>
&lt;p>這題如果以暴力法來解決的話，我們可以拿到的總連續子陣列數是&lt;br>
N+(N-1)+(N-2)+…+1，每個子陣列中的計算下一組和(如[-2] -&amp;gt; [-2,1])，&lt;br>
都只需一個加法，故時間複雜度會是O(N²)。&lt;/p>
&lt;p>但&amp;hellip;&amp;hellip;感覺很浪費(?)&lt;br>
我們先思考一個問題：&lt;br>
「假設我知道nums中1到i-1的最大子陣列和，&lt;br>
有沒有辦法知道1到i的最大子陣列和呢？」&lt;br>
我們討論1到i的最大子陣列和，應該分兩種情況：&lt;br>
a. &lt;strong>這個子陣列包括index i&lt;/strong>&lt;br>
b. &lt;strong>這個子陣列不包括index i&lt;/strong>&lt;br>
如果是&lt;strong>b&lt;/strong> 的話，那答案其實就是&lt;strong>1到i-1的最大子陣列和&lt;/strong> ；&lt;br>
但如果是&lt;strong>a&lt;/strong> 的話，我們好像還需要一些條件？&lt;br>
什麼條件呢？就是&lt;strong>1到i-1中，包含i-1元素的最大子陣列和&lt;/strong> 。&lt;br>
因為如果是前面所提到的a狀況的話，&lt;br>
那麼1到i的最大連續子陣列，就必須從i-&amp;gt;i-1連回去才行(或乾脆是只有i)。&lt;/p>
&lt;p>所以這麼一來，條件就比較清楚了，我們會需要的有：&lt;/p>
&lt;ol>
&lt;li>到現在為止&lt;strong>包含當前這個元素的最大子陣列和&lt;/strong> ，我們命名為curr(current)&lt;/li>
&lt;li>到目前為止的&lt;strong>最大子陣列和&lt;/strong> ，我們命名為res(result)&lt;/li>
&lt;/ol>
&lt;p>那麼我們就以範例的[-2,1,-3,4,-1,2,1,-5,4]來操作看看。&lt;br>
該怎麼決定curr跟res的初始值呢？因為一開始只有一個值，&lt;br>
所以curr和res應該都等於nums[0]=-2才對。&lt;br>
所以一開始我們將curr和res都設為-2，接下來由i=1開始，&lt;br>
一路往下到最後一個結束。&lt;/p>
&lt;p>i=1: [-2,&lt;em>&lt;strong>1&lt;/strong> *,-3,4,-1,2,1,-5,4]&lt;br>
按我們的定義，curr應該是-2+1和1中較大的值，&lt;br>
我們可以先將curr加上nums[1]，&lt;br>
接下來檢查&lt;/em>&lt;em>curr小於0&lt;/em>* ，或者&lt;strong>curr&amp;lt;nums[1]&lt;/strong> ，&lt;br>
就表示其實我們只要取&lt;strong>nums[1]&lt;/strong> 就好。&lt;br>
(註1: 表示兩者的正負號為**(-, -), (-, +)** ，不論如何&lt;strong>前面那部分貢獻均是負的&lt;/strong> )&lt;br>
(註2: 也可以拆成別的形式或調換順序，但先判斷&amp;lt;0的計算速度會比較快)&lt;br>
(註3: 後面程式碼Java和Python的判斷方式就不同，可自行依喜好決定使用)&lt;br>
所以新的curr為1, 接著再比較得知curr&amp;lt;res，故res也要改為1。&lt;br>
接下來的流程，讀者可以嘗試自己操作一遍再對照一下。&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=2: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 1 + -3 = -2 &amp;lt; 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = -3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; res = 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=3: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = -3 + 4 = 1 &amp;lt; 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; res = 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=4: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 4 + -1 = 3 &amp;gt; -1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=5: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 3 + 2 = 5 &amp;gt; 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; res = 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=6: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 5 + 1 = 6 &amp;gt; 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; res = 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=7: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 6 + -5 = 1 &amp;gt; -5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>i=8: [-2,1,-3,4,-1,2,1,-5,4]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-&amp;gt; curr = 1 + 4 = 5 &amp;gt; 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>所以最後我們得到res = 6，再回傳即可。&lt;/p>
&lt;p>這個解法第一次並不是很容易上手，而且並非相當直觀的方式，&lt;br>
但它常常可以在特別的地方有效地解決問題。&lt;br>
適用於這類型的解法的問題會有一個特性：&lt;br>
&lt;strong>「N=i+1時的解，通常和N=i時的解以及第i+1的值有關連性」&lt;/strong>&lt;br>
(也有可能跟更前面幾個值同時有關連性)&lt;br>
而我們通常很難直觀地直接用簡單的方式去算出N=i+1的解，&lt;br>
所以會依靠其本身和前面的連動關係，&lt;br>
讓答案像堆積木一樣，從i=0開始堆到最後面得到最終的答案。&lt;/p>
&lt;p>有些問題可能未必是一層一層疊上去，&lt;br>
也有可能是把一個大問題拆成數個小問題，&lt;br>
最後將其組合起來得到大問題的答案。&lt;br>
但通常我們最常見的形式還是如上面那樣子按順序堆疊的。&lt;/p>
&lt;p>上面這樣子形式的解題方法，&lt;br>
被稱之為&lt;strong>動態規劃(Dynamic Programming)&lt;/strong> ，或者也常簡稱為DP。&lt;br>
每個動態規劃的問題都會有些不一樣，&lt;br>
但只要抓到其中的連動性，找到從&lt;strong>i -&amp;gt; i+1&lt;/strong> 中間的關聯，&lt;br>
就可以順利解開題目。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7847030300839993b7b6f7cbf723ded2.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/37fa93e5c41056d82306906bee93ad2d.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間/空間複雜度？」&lt;br>
(O(N), O(1))&lt;/p>
&lt;p>「如果不使用DP是否有O(N)解？」&lt;br>
(可以使用分治法，請參見 &lt;a class="link" href="https://leetcode.com/problems/maximum-subarray/discuss/20372/How-to-solve-%22Maximum-Subarray%22-by-using-the-divide-and-conquer-approach" target="_blank" rel="noopener"
>*&lt;strong>LeetCode這篇討論&lt;/strong> *&lt;/a>底下的回應)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 6 Binary Search</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-6-binary-search/</link><pubDate>Wed, 03 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-6-binary-search/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 6 Binary Search" />&lt;p>&lt;strong>0035. Search Insert Position (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.&lt;/p>
&lt;p>You may assume no duplicates in the array.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,3,5,6], 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,3,5,6], 2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-3">Example 3
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,3,5,6], 7
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-4">Example 4
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [1,3,5,6], 0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>給定一個排序的陣列和目標值，假定陣列的數字不會重複。&lt;br>
題目要求找到目標值在這個陣列中的位置；&lt;br>
若無，則回傳如果要將其插入時，應插入的位置。&lt;/p>
&lt;p>這題是很典型的二元搜索法(&lt;strong>Binary Search)&lt;/strong> 。&lt;br>
所謂的Binary Search，就是資料已處於被排序的狀態，那麼在這些資料內搜索某個特定值就不用一個一個找，我們可以用比較快的方法來搜尋。&lt;br>
假設我們有一組排序過的陣列，&lt;br>
搜尋的第一步就是取得中間點的那個值，我們先稱之為mid，&lt;br>
那&lt;strong>mid左邊的數必然小於mid，反之mid右邊的數必然大於mid&lt;/strong> 。&lt;br>
(按順序排的嘛XD)&lt;br>
所以我們拿目標值target跟mid比較，&lt;br>
如果&lt;strong>target == mid&lt;/strong> ，那&lt;strong>mid所在的位置&lt;/strong> 就是我們要的答案；&lt;br>
如果&lt;strong>target &amp;gt; mid&lt;/strong> ，表示答案只可能在&lt;strong>mid右邊到尾端之間(不含mid)&lt;/strong> ；&lt;br>
如果&lt;strong>target &amp;lt; mid&lt;/strong> ，表示答案只可能在&lt;strong>mid左邊到開頭之間(不含mid)&lt;/strong> 。&lt;br>
如此一來，每次取得區塊的中間點的值，並和target做比較，&lt;br>
則&lt;strong>每次都可以至少刪掉一半的可能的數量&lt;/strong> ，&lt;br>
直到&lt;strong>找到答案(target == mid)&lt;/strong> ，&lt;br>
或是&lt;strong>區塊上下限交錯(那就表示target不存在於陣列之中)&lt;/strong> ，&lt;br>
我們同樣可以將&lt;strong>下限&lt;/strong> 的index輸出，因為它就代表應該被插入的點。&lt;/p>
&lt;p>例1. nums=[1,3,5,6], target=2 &lt;br>
首先取下限lo = 0, 上限up = 3(頭跟尾), 中間點mi = (lo + up) / 2 = 1 -&amp;gt;&lt;br>
nums[1]為3, 3 &amp;gt; 2 -&amp;gt; 將up改為mi-1=0 -&amp;gt; mi = (0 + 0) / 2 = 0 -&amp;gt;&lt;br>
nums[0]為1, 1 &amp;lt; 2 -&amp;gt; 將lo改為mi+1=1 -&amp;gt; &lt;br>
lo和up已交叉，故結果應輸出1。&lt;/p>
&lt;p>中間的值的變化如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>lo up mi nums[mi]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 3 1 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 0 0 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1 0 0 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>例2. nums=[1,3,5,6], target=5&lt;br>
首先取下限lo = 0, 上限up = 3(頭跟尾), 中間點mi = (lo + up) / 2 = 1 -&amp;gt;&lt;br>
nums[1]為3, 3 &amp;lt; 5 -&amp;gt; 將lo改為mi+1=2 -&amp;gt;mi = (2+3)/2 = 2 -&amp;gt;&lt;br>
nums[2]為5, 5==5 -&amp;gt; 直接輸出mi的值2即是答案。&lt;/p>
&lt;p>中間的值的變化如下：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>lo up mi nums[mi]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 3 1 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2 3 2 5
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>下面也列出[1,3,5,6], 7跟[1,3,5,6], 0的值變化的過程，&lt;br>
有興趣或對整個邏輯還沒有弄得很明白的讀者可以嘗試推導一遍。&lt;/p>
&lt;p>nums=[1,3,5,6], target=7 -&amp;gt; ans = 4&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>lo up mi nums[mi]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 3 1 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2 3 2 5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>3 3 3 6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>4 3 3 6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>nums=[1,3,5,6], target=0 -&amp;gt; ans = 0&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>lo up mi nums[mi]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 3 1 3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 0 0 1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0 -1 -1 6 #(這個是用python輸出的，所以nums[-1] == 6)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>底下的解法看個人喜好命名均可。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/1e8ce8f5cb9f93d7735cddc4acd5fad0.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/97cea741906acfed250c644a263524df.js">&lt;/script>
&lt;p>在這個解題過程，由於每次我們都會將範圍縮小一半，&lt;br>
所以總共比對的次數就相當於求這個陣列的長度是2的幾次方，&lt;br>
故時間複雜度為&lt;strong>O(logN)&lt;/strong> 。&lt;br>
(電腦科學領域的對數一般不特別提的話通常是以2為底)&lt;/p>
&lt;p>事實上，Java中也有提供 &lt;strong>Arrays.binarySearch(int[] a, int key)&lt;/strong> 於utils的函式庫中，但有一點不一樣的是，當找不到target的時候，&lt;br>
如果插入該key所在位置為index，則回傳值為**-index-1** 。&lt;br>
取負號是為了和key存在於陣列的狀況做分隔，&lt;br>
額外減1則是為了將&lt;strong>key在0的位置&lt;/strong> 及&lt;strong>key應該要插入在0的位置&lt;/strong> 做區分。&lt;br>
(因為0取負號還是0)&lt;/p>
&lt;p>Binary Search是在排序陣列或一些有序的資料結構中很常用到的演算法，&lt;br>
以後在談到&lt;strong>二元搜尋樹(BST, Binary Search Tree)&lt;/strong> 的時候也會用到它。&lt;br>
所以如何寫一個二元搜尋的簡單方法是很有用的，可以的話務請熟練XD&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「(Java)如果上限接近Integer.MAX_VALUE的話相加有overflow的可能？」&lt;br>
(將(lo+up)/2改成lo + (up-lo)/2，可以保證不會溢出)&lt;/p>
&lt;p>「時間/空間複雜度？」&lt;br>
(O(logN), O(1))&lt;/p>
&lt;p>「我想知道到底結果target是否存在array中，但不想額外加回傳的值？」&lt;br>
(如上面提到的，將&lt;strong>插入&lt;/strong> 的狀況改為**-index-1** 來表達)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 5 In-Place</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-5-in-place/</link><pubDate>Tue, 02 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-5-in-place/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 5 In-Place" />&lt;p>&lt;strong>0026. Remove Duplicates from Sorted Array (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given a sorted nums array, remove the duplicates &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
>&lt;strong>in-place&lt;/strong> &lt;/a> such that each element appears only &lt;em>once&lt;/em> and return the new length.&lt;/p>
&lt;p>Do not allocate extra space for another array, you must do this by &lt;strong>modifying the input array&lt;/strong> &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
>** in-place**&lt;/a> with O(1) extra memory.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given nums = [1,1,2],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>It doesn&amp;#39;t matter what you leave beyond the returned length.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given nums = [0,0,1,1,1,2,2,3,3,4],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>It doesn&amp;#39;t matter what values are set beyond the returned length.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求將一個已排序陣列中所有的重複數字刪去，使得這個陣列的每個數字只出現一次，並且必須要以in-place的方式來處理。&lt;br>
最終處理過後，回傳新陣列的長度。&lt;/p>
&lt;p>題目其實並不困難，設定一個i用來記錄目前存放到哪個位置，&lt;br>
再設定一個j用以完整遍歷整個陣列，&lt;br>
每當發現有不同的數字時，就將j的數字塞到i的位置，再往下推進即可。&lt;/p>
&lt;p>最後由於要回傳的是新陣列的長度，所以應該要回傳i+1。(陣列由0開始)&lt;/p>
&lt;p>這邊要順便提到的一個名詞叫&lt;strong>in-place algorithm&lt;/strong> 。&lt;br>
所謂的in-place，就是指所有的操作修改，除了一些計數用的變數外，&lt;br>
&lt;strong>基本上都在原先的資料結構內解決&lt;/strong> ，像這題就是完全只有操作原陣列。&lt;br>
如果沒有這樣的限制，這題也是可以使用ArrayList，每當發現一個不同的數就將其往List尾端加，最後再將其轉為array，&lt;br>
同樣可以得到解，但它的空間複雜度就會變成O(N)，&lt;br>
因為我們開了一組額外的記憶體來存放它。&lt;/p>
&lt;p>所以in-place algorithm會應用在一些&lt;strong>不希望大量增加記憶體使用量&lt;/strong> 的狀況，且在這個限制條件下，有時候我們不一定能像這題這樣得到跟非in-place時一樣時間複雜度的解法。&lt;br>
所以&lt;strong>in-place algorithm通常會有拿時間換取空間效率的狀況&lt;/strong> 。&lt;br>
總之，如果&lt;strong>原先的資料被修改或打亂也沒關係&lt;/strong> 的話，&lt;br>
就有使用in-place algorithm的機會，也有可能會被面試官問到，&lt;br>
但請務必謹慎地確認是否這個狀況下，&lt;br>
你真的會必須用比較差的時間複雜度達到相同的目的。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/17ad6dbe70bef408aa2c3c40cb00acaf.js">&lt;/script>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/b2f59727e08875fcd99cafd47189da77.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「時間複雜度跟空間複雜度為？」(O(N), O(1))&lt;/p>
&lt;p>「如果不要求in-place，改成新開list/arraylist來做會比較快嗎？」&lt;br>
(不會，因為時間複雜度相同，但要額外花時間做記憶體配置)&lt;/p>
&lt;p>「如果題目今天給的是未排序陣列要去除duplicate，&lt;br>
但不用in-place，也不用保留順序的話？」&lt;br>
(使用HashMap/dict，將整個陣列掃過一遍，最後遍歷輸出)&lt;br>
(時間/空間複雜度為O(N), O(N))&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 4 Linked List (1)</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-4-linked-list-1/</link><pubDate>Mon, 01 Jul 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-4-linked-list-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 4 Linked List (1)" />&lt;p>&lt;strong>0021. Merge Two Sorted Lists (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: 1-&amp;gt;2-&amp;gt;4, 1-&amp;gt;3-&amp;gt;4
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: 1-&amp;gt;1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求將兩個已排序的linked lists合併，&lt;br>
且所產生的新list必須由原有的節點(node)所構成。&lt;/p>
&lt;p>Linked List是一個很常見的資料結構，資料與資料連接的方式是單向的，&lt;br>
通常從第一個節點(node)往後連接到最後一個節點(node)。&lt;br>
每個節點上會存放一個(或一組)資料以及連結(link)，&lt;br>
每個連結會&lt;strong>指向到下一個節點&lt;/strong> 的位置(記憶體位址)。&lt;br>
(在C/C++裡面連結基本上就是指標(pointer))&lt;/p>
&lt;p>你可能會問，那麼最後一個節點呢?&lt;br>
最後一個節點除了儲存資料以外，因為連結沒有東西了，所以會給定空值。在演算法的書中一般會稱為&lt;strong>NIL&lt;/strong> ，NIL在英文裡面就是&lt;strong>nothing&lt;/strong> 的意思，&lt;br>
表示沒有任何東西。&lt;/p>
&lt;p>在Java中有LinkedList的資料結構，它同樣是List的一種。&lt;br>
但一般遇到題目的時候會給的通常是一個node，&lt;br>
用來指向到該List的第一個節點。&lt;/p>
&lt;p>我們會看到如果你打開LeetCode選擇Java時，&lt;br>
上方已經先用註解告訴你這個ListNode的結構了：&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">6
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">7
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>/**
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * Definition for singly-linked list.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * public class ListNode {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * int val;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * ListNode next;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * ListNode(int x) { val = x; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> */
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>也就是說，題目預先定義了一個class叫做ListNode，&lt;br>
&lt;strong>val用來存放每個node的值，next用來指向到下一個node&lt;/strong> ，&lt;br>
有一個&lt;strong>ListNode(int x)&lt;/strong> 的建構子(constructor)，&lt;br>
可以讓你在產生一個新的節點時給定其值。&lt;/p>
&lt;p>對於LinkedList來說，它最大的好處在於新增/刪除節點時相當方便。&lt;br>
例如現在有a-&amp;gt;b，我想要加一個資料值為20的c節點，放在b後面的話，&lt;br>
以Java而言只需要:&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>ListNode b = a.next; // 因為一開始我們只知道a的位置而已XD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ListNode c = new ListNode(20);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>b.next = c;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如果是插入在a跟b中間呢？也不難，&lt;br>
只是我們要先記住b，不然一旦沒有人記它，它就消失在時空裂縫中了(誤)&lt;br>
(會依照各自編譯器的規範，只是以我們而言是真的就沒辦法找到它了)&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>// a -&amp;gt; c -&amp;gt; b
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ListNode b = a.next;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ListNode c = new ListNode(20);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>a.next = c;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>c.next = b;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>請留意如果你調動了一些節點的順序，留意他們的next是否被妥善處理，&lt;br>
該被清空的請給定NIL。&lt;strong>在Java中是用null來表示，而Python則是用None。&lt;/strong> 回到題目，我們該如何去合併排列好的兩個LinkedList呢？&lt;br>
這邊提供一個很簡單的遞迴思路。&lt;br>
(遞迴的概念，我們之後再專門做一篇相關的來講解)&lt;br>
我們合併兩個list的狀況目標還是要呈現排序好的樣子，&lt;br>
那麼怎麼排呢？&lt;br>
由於原先的list已經是排好的，&lt;br>
我們拿出最左邊的node比較，稱為l1跟l2。&lt;br>
l1是全空的狀況下，那其實答案就是l2(因為後面就不用繼續排了)，&lt;br>
反之l2是全空的話，答案就是l1。&lt;br>
那麼如果l1的值小於l2的值的話，那麼l1應該要當頭，&lt;br>
接下來我們要拿&lt;strong>l1.next&lt;/strong> 跟&lt;strong>l2&lt;/strong> 來做比較大小，比較小的，&lt;br>
就會是新的l1連接的下一個節點。&lt;br>
一直連接到最後，我們就可以得到合併好的list了！&lt;br>
相等的狀況因為題目沒有特別要求要分辨是l1還是l2的節點，&lt;br>
所以任取一個均可。&lt;/p>
&lt;p>例：&lt;br>
l1: 1 -&amp;gt; 3 -&amp;gt; 5 -&amp;gt;8 -&amp;gt;10, l2: 2 -&amp;gt; 4 -&amp;gt; 4&lt;br>
1先跟2比，1比較小所以當頭(1) -&amp;gt; &lt;br>
3跟2比，2比較小(1-&amp;gt;2) -&amp;gt;&lt;br>
3跟4比(1-&amp;gt;2-&amp;gt;3) -&amp;gt;&lt;br>
5跟4比(1-&amp;gt;2-&amp;gt;3-&amp;gt;4) -&amp;gt;&lt;br>
5跟4比(1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;4) -&amp;gt;&lt;br>
l2的部分已經空了，填入l1中5以後剩下的部分&lt;br>
(1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;4-&amp;gt; 5 -&amp;gt;8 -&amp;gt;10)&lt;/p>
&lt;p>寫成Java的程式如下。&lt;/p>
&lt;p>Java:&lt;/p>
&lt;script src="https://gist.github.com/Desolve/c5a4635fff728970132bbda438a1203e.js">&lt;/script>
&lt;p>當然我們也可以用迴圈(迭代)的方法來解，&lt;br>
但這時候我們就要比較仔細的去處理節點間的關係了。&lt;br>
在Python中判斷是否為None可以使用if，&lt;br>
通過if的話節點就代表該節點是有值的，&lt;br>
你也可以加入not的關鍵字來處理你所需要的判斷式。&lt;br>
比如我可以用if not (l1 and l2)來表達其中一個以上是空的狀況，&lt;br>
並回傳不是None的那個node。&lt;/p>
&lt;p>操作上，我們需要一個dummy node做為旁觀者，&lt;br>
讓它從頭到尾都只&lt;strong>保持在同樣的位置&lt;/strong> ，並指向到第一個節點。&lt;/p>
&lt;p>接著我們定義一個節點叫做prev，&lt;br>
&lt;strong>prev的next&lt;/strong> 會指定給下一個比較過後&lt;strong>較小的那個節點&lt;/strong> 。&lt;br>
那麼，每次將prev的next拿到以後，&lt;br>
l1或l2(看哪個比較小)就自己&lt;strong>遞移到下一個節點&lt;/strong> ，&lt;br>
並且prev也往下走到自己的next，準備接取下一個節點；&lt;br>
重覆上面的動作&lt;strong>直到其中一邊節點用光&lt;/strong> ，&lt;br>
即可把剩下的直接全接到prev.next上。&lt;/p>
&lt;p>最終我們回傳的答案是&lt;strong>dum.next&lt;/strong> ，因為只有dum沒有被動過，&lt;br>
其他的節點其實都已經被改動過指向的位址了。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/7b3daa901e07ed8cf45983a68f552c9e.js">&lt;/script>
&lt;p>在有關linked list的部分，因為牽扯到位址的概念，&lt;br>
所以操作上要稍微再思考一下，比較不容易搞混。&lt;br>
最重要的是，對於Java和Python來說，由於所使用的都是class來建立node，&lt;br>
所以其實你看到的等號，除了給定val的狀況以外，&lt;br>
其他其實都是在做&lt;strong>把右邊放的記憶體位址存到左邊&lt;/strong> 的動作，&lt;br>
所以&lt;strong>指向的記憶體位址變了，代表的節點也就跟著變了&lt;/strong> ，務必要留意這點。&lt;/p>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「請用iterative(迭代或迴圈)/recursive(遞迴)的方式來解」&lt;br>
(上面Java是recursive solution，Python是iterative solution，&lt;br>
讀者可以嘗試改成另一個語言試看看)&lt;/p>
&lt;p>「使用遞迴的話會有什麼限制？」&lt;br>
(有可能受到編譯器規範的最大function stack上限限制，&lt;br>
同時，連續的函式呼叫的效率，相對於在迴圈中執行來說會較差)&lt;/p>
&lt;p>「那為什麼你會用遞迴？」&lt;br>
(因為遞迴比較好想啊XDDDDD)(別這麼誠實，雖然大家都知道XD)&lt;br>
(因為在一般狀況下，遞迴解通常會較為容易閱讀，&lt;br>
也比較符合人類的思路模式，就像推骨牌一樣，&lt;br>
當起始條件和後續的脈絡定下來以後，後面的結果就會水到渠成。)&lt;/p>
&lt;p>「時間複雜度是？」&lt;br>
( worst case是O(N1+N2)，best case是O(min(N1, N2))。)&lt;/p>
&lt;p>「如果希望你另外開一個新的linked list，不用原本的節點來解這題呢？」&lt;br>
(這樣會比較簡單，一樣兩兩比較，但改成較小的取其val來產生一個新的ListNode，接在你的新的linked list後面，讀者可以嘗試看看，&lt;br>
別忘記要留dummy node歐！)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 3 Two Pointers</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-3-two-pointers/</link><pubDate>Sat, 29 Jun 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-3-two-pointers/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 3 Two Pointers" />&lt;p>&lt;strong>0015. 3Sum (Medium)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array &lt;code>nums&lt;/code> of &lt;em>n&lt;/em> integers, are there elements &lt;em>a&lt;/em>, &lt;em>b&lt;/em>, &lt;em>c&lt;/em> in &lt;code>nums&lt;/code>such that &lt;em>a&lt;/em> + &lt;em>b&lt;/em> + &lt;em>c&lt;/em> = 0? Find all unique triplets in the array which gives the sum of zero.&lt;/p>
&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;p>The solution set must not contain duplicate triplets.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given array nums = [-1, 0, 1, 2, -1, -4],
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">4
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>A solution set is:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [-1, 0, 1],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [-1, -1, 2]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求從陣列中找出所有數組a, b, c，&lt;br>
使得三者相加為0，且不能重覆。&lt;/p>
&lt;p>老話一句，&lt;strong>請記得問有沒有排序XD~&lt;/strong>&lt;br>
以暴力法解本題的話，會發現每次取三個做組合，&lt;br>
顯然會得到一個O(N³)的時間複雜度的解。&lt;br>
那麼，嘗試排序看看能得到比較好的解嗎？&lt;br>
我們先拿題目的例子來看看，排序過後為&lt;br>
[-4, -1, -1, 0, 1, 2]&lt;br>
按順序排列會有什麼好處呢？&lt;br>
假設我們先固定最左邊的-4為a(因為要組合，我們可以令a&amp;lt;=b&amp;lt;=c)，&lt;br>
那麼b+c必須等於4，這邊使用一個簡單的技巧，&lt;br>
先將b指定給-1的位置，c指定給2的位置，&lt;br>
兩者相加等於1，表示&lt;strong>應該要取更大的值&lt;/strong> 才有機會讓和等於4，&lt;br>
於是我們可以將b的位置向右移一格(這裡是重覆的所以可以跳過)，&lt;br>
再次檢查和目標的大小比較。&lt;/p>
&lt;p>那麼很容易可以發現一件事情：&lt;br>
當現在的值比目標值&lt;strong>大&lt;/strong> 時，表示&lt;strong>應該要取更小的值&lt;/strong> ，&lt;br>
只有&lt;strong>將c往左移動&lt;/strong> 才有可能達到。&lt;br>
反之，&lt;br>
當現在的值比目標值&lt;strong>小&lt;/strong> 時，表示&lt;strong>應該要取更大的值&lt;/strong> ，&lt;br>
只有將&lt;strong>b往右移動&lt;/strong> 才有可能達到。&lt;br>
因此，在固定a值的時候，只要將後面的數按照上面的方法，&lt;br>
一次移動一格的掃過一遍，就可以得到這個a值所可以成立的組合。&lt;/p>
&lt;p>所以最終我們只要將a從0~len(nums)-3按順序跑過一遍，&lt;br>
將中間符合的組合都放進list中，即可得到答案。&lt;/p>
&lt;p>重覆性的部分，只要記得檢查前一個和這一個用的數字是否相同即可避免。&lt;/p>
&lt;p>上述的做法，由於使用到兩個指標(指針)，並透過移動它們來達到掃描陣列的目的，我們通常稱這樣的解法為&lt;strong>Two Pointer&lt;/strong> ，是蠻常用的技巧。&lt;br>
時間複雜度的部分，排序的一般狀況是O(NlogN)，&lt;br>
而a的長度是O(N)，每次都要掃完其後的長度，掃描部分即為O(N²)，&lt;br>
所以總體的時間複雜度為O(N²)。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/075ff6e7224a53d85c2acaf0c6b73b6e.js">&lt;/script>
&lt;p>這邊使用i, j, k標記，要用a, b, c也可XD&lt;br>
使用Arrays.asList可以將一串元素塞成ArrayList。&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;p>Python的部分提供了另一個的思路，&lt;br>
這是由 &lt;a class="link" href="https://leetcode.com/rouroukerr" target="_blank" rel="noopener"
>RouRouKerr&lt;/a>在討論區所提出的解法，這邊是改成Python3版本。&lt;br>
他的想法是，在固定第一個數v的狀況，那當其中一個數為x，&lt;br>
另一個數只能是-v-x(因為加總要等於0)。&lt;br>
故每次將對應的互補數加入到dict中，&lt;br>
我們只要從頭到尾檢查，即可得到所有的正確組合。&lt;br>
這個想法跟前面Two Sum的解法概念是一樣的。&lt;br>
(對應到Java版本的解法也附在註解處)&lt;/p>
&lt;script src="https://gist.github.com/Desolve/6c1a4c1f6b3fad320f8f5e5b0bbcbb5b.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「(Python)前面不檢查的話後面你怎麼處理重覆？」(用set)&lt;br>
「假設目標不是0的話？」(方法應該是一樣的)&lt;br>
「(Python)dictionary的部分使用set代替會比較快嗎？」(實測過會變慢XD)&lt;br>
「(Java)如果可以改變input/output的變數形態的話，你會希望改動什麼？」&lt;br>
(改output，因為輸出應該固定會是3元組的組合(長度必然是3)，&lt;br>
那大可以使用List&amp;lt;int[]&amp;gt;，用List&amp;lt;List&lt;Integer>&amp;gt;其實較不理想)&lt;/p>
&lt;p>只要掌握了Two Pointers的概念，很多題目其實可以在排序後輕鬆解決，&lt;br>
但記得注意有些題目可以比O(NlogN)快的話，排序會提高時間複雜度歐！&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 2</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-2/</link><pubDate>Fri, 28 Jun 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-2/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 2" />&lt;p>&lt;strong>0014. Longest Common Prefix (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Write a function to find the longest common prefix string amongst an array of strings.&lt;/p>
&lt;p>If there is no common prefix, return an empty string &lt;code>&amp;quot;&amp;quot;&lt;/code>.&lt;/p>
&lt;h3 id="example-1">Example 1
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [&amp;#34;flower&amp;#34;,&amp;#34;flow&amp;#34;,&amp;#34;flight&amp;#34;]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;fl&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="example-2">Example 2
&lt;/h3>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Input: [&amp;#34;dog&amp;#34;,&amp;#34;racecar&amp;#34;,&amp;#34;car&amp;#34;]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Output: &amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Explanation: There is no common prefix among the input strings.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Note:&lt;/strong>&lt;/p>
&lt;p>All given inputs are in lowercase letters &lt;code>a-z&lt;/code>.&lt;/p>
&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求從一組字串陣列中找出其最長的共用前綴，&lt;br>
字串只會由a到z所構成，若沒有的話則回傳空字串。&lt;/p>
&lt;p>同樣的，若遇到這個問題，請第一時間記得問他們有沒有排序XD&lt;br>
依據資料的分布不同，不同的解法應該會有不同的優勢，&lt;br>
但非特殊情況的話，總體時間複雜度應為: O(單一字串長 * 總字串數)&lt;/p>
&lt;p>最直觀的想法，就是從頭開始將每個相同位置的字元比對一次，&lt;br>
相同則往下繼續做，不同則停下將結果輸出，&lt;br>
但這麼做可能前面每次都要掃過相同位置的所有字元。&lt;/p>
&lt;p>我們可以換個角度想，若先拿第一個字串當作common prefix(命名作pre)，&lt;br>
接下來用其餘的字串來檢查這個pre是否是其prefix，是的話則檢查下一個，&lt;br>
不是的話就將pre的尾端刪去重新檢查，這樣一旦當中有一個字串有大幅度差異，我們很快就能將pre縮減到很短。&lt;/p>
&lt;h3 id="java">Java
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/4b883bbe1327d14edb1f848417315857.js">&lt;/script>
&lt;p>留意這當中我們使用了String.indexOf()來檢查，&lt;br>
我們只想要pre在剛好0的位置，所以不論這個值是&amp;gt;0(表示出現在中間)&lt;br>
或&amp;lt;0(根本沒出現)，都代表pre需要被調整。&lt;br>
實測上這個解是當前LeetCode上對test cases跑最快的版本(0 ms)。&lt;/p>
&lt;p>如果是Python的話，會有比較有趣的解法。&lt;br>
Python支援的min()和max()可以讓我們在List[str]中列出&lt;strong>依字母排列順序&lt;/strong> 最小和最大的字串。當我們可以很簡單拿到這個值時，&lt;br>
我們可以換一個思路，從頭到尾比較的時候，我們其實只需比最小和最大的兩個字串就好，當它們是相同字元時則往下繼續，否則就回傳至目前為止的substring。(因為排序最大和排序最小在某個index字元相同時，即代表著中間其他字串在此index字元亦相同)&lt;/p>
&lt;h3 id="python">Python
&lt;/h3>&lt;script src="https://gist.github.com/Desolve/ea83da7ad0a06d46dcf7be4d55536072.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>「如果不能用indexOf的話你會怎麼做？」&lt;br>
(可使用String.toCharArray()轉成陣列後再操作)&lt;br>
「如果這組陣列被預期長短差異很大呢？」&lt;br>
(先掃過一遍陣列，拿最短的當pre)&lt;br>
「Best Case和Worst Case的時間複雜度？什麼狀況下會發生？」&lt;br>
(依照你的解法應該有所不同)&lt;br>
「如果加入&amp;lt;0的判斷式的話可以提升這個程式的效率嗎？」&lt;br>
(不一定，因為&lt;strong>不保證多快能遇到前綴完全不同的字串&lt;/strong> ，&lt;br>
所以端看這組資料是預期很有可能出現結果為空字串，&lt;br>
還是大多數都會有共同前綴來決定。)&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 1</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-1/</link><pubDate>Thu, 27 Jun 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-1/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 1" />&lt;p>&lt;strong>0001. Two Sum (Easy)&lt;/strong>&lt;/p>
&lt;h2 id="question">Question
&lt;/h2>&lt;p>Given an array of integers, return &lt;strong>indices&lt;/strong> of the two numbers such that they add up to a specific target.&lt;/p>
&lt;p>You may assume that each input would have *&lt;strong>exactly&lt;/strong> * one solution, and you may not use the &lt;em>same&lt;/em> element twice.&lt;/p>
&lt;p>&lt;strong>Example:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Given nums = [2, 7, 11, 15], target = 9,
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;">&lt;tr>&lt;td style="vertical-align:top;padding:0;margin:0;border:0;">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">1
&lt;/span>&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>Because nums[0] + nums[1] = 2 + 7 = 9,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>return [0, 1].
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="分析解題">分析/解題
&lt;/h3>&lt;p>題目要求是，在一組陣列中找出兩個數，其加總恰等於給定值。&lt;br>
每個數不能被重複使用，且必剛好只有一個解。&lt;br>
像這種題目，由於被擺在第一題，大多數狀況都不會被拿來考XD&lt;br>
但，凡事總有例外。&lt;/p>
&lt;p>我們先來分析一下，如果按照原題的要求該怎麼解。&lt;br>
如果input長度為N，那麼暴力解就是將數字兩兩相加看是不是解，&lt;br>
這樣的解法要算N(N-1)/2次，也就是O(N²)的時間複雜度。&lt;/p>
&lt;p>該怎麼降低複雜度呢？我們會希望每個數只要查一次就知道結果，&lt;br>
有沒有這樣的結構？當然有，在Java中可以用&lt;strong>HashMap&lt;/strong> ，&lt;br>
而在Python中可以用&lt;strong>dictionary&lt;/strong> 。&lt;/p>
&lt;p>只要每一次從map中確認當下target-num是否在map中，&lt;br>
在的話就表示找到了，可以將結果取得，&lt;br>
沒找到的話，就將一組(num, index)放進map中，&lt;br>
依此流程，最壞的狀況整個array遍歷後，就可以得到答案。&lt;/p>
&lt;p>時間複雜度：&lt;br>
由於HashMap在put和get最好的狀況都是O(1)，&lt;br>
遍歷整個Map需要O(N)。&lt;/p>
&lt;p>Java:&lt;/p>
&lt;script src="https://gist.github.com/Desolve/1b5deb87574dc16aa0a51d9a07a9fb2c.js">&lt;/script>
&lt;p>Python:&lt;/p>
&lt;script src="https://gist.github.com/Desolve/e936fe7cbad8aa7810eeffacebadda41.js">&lt;/script>
&lt;h2 id="面試實際可能會遇到的問題">面試實際可能會遇到的問題
&lt;/h2>&lt;p>這裡有一個原則：&lt;br>
***不論是什麼問題，不論你當下想到的方法有多暴力有多爛，&lt;br>
有想到方法就先講沒關係。***以這題為例，你應該先提出最先的O(N²)解，大概描述完以後，&lt;br>
再說但這樣時間複雜度比較高，&lt;br>
&lt;strong>如果應用HashMap(python用dict)的話，&lt;br>
可以讓每個數只需要花O(1)作搜尋，複雜度就會降到O(N)。&lt;/strong>&lt;/p>
&lt;p>先講出一個可能的解法，再想辦法延伸修改或者改進它，&lt;br>
這是大多數公司建議(尤其Google)的方式，&lt;br>
一來可以讓面試官知道你不是腦袋空空，至少先有個基本分，&lt;br>
二來在講這個暴力解時，你可以有緩衝的時間去想更好的解法。&lt;/p>
&lt;p>還有一些需要注意的東西可以做為你和面試官互動和溝通的部分，&lt;br>
或有可能是面試官問你的進一步問題，&lt;br>
在平常每題解完後，都應該留點時間給自己去思考一下可能的變化。&lt;br>
以此題為例：&lt;br>
「請問這個陣列是否是排序好的？」(排好的解法就又不同了XD)&lt;br>
「如果我想要的是回傳那兩個數字而非indices的話呢？」(修改pair即可)&lt;br>
「你剛剛提到了排序，那怎樣的狀況先對陣列作排序會比較好？」&lt;br>
「如果答案存在很多組，能否找出所有的解？」&lt;br>
「如果當中存在重覆的數字的話呢？」&lt;br>
「為什麼HashTable/HashMap的存取是O(1)？」(這可能就扯比較遠了XD)&lt;br>
「那麼它們的worst case呢？什麼狀況下會發生？」&lt;/p>
&lt;p>從LeetCode學演算法，我們下次見囉，掰~&lt;/p></description></item><item><title>從LeetCode學演算法 - 0</title><link>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/</link><pubDate>Wed, 26 Jun 2019 00:00:00 +0800</pubDate><guid>https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/</guid><description>&lt;img src="https://learnwithdesolve.netlify.app/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 0" />&lt;p>&lt;strong>你應該知道的面試基礎和解題技巧&lt;/strong>&lt;/p>
&lt;p>&lt;strong>What is an algorithm?&lt;/strong>&lt;/p>
&lt;p>所謂的演算法，就是描述一個計算/操作的過程，&lt;br>
這個過程可以用有限的長度來描述如何解決問題。&lt;br>
或者更簡單的說法：&lt;br>
*&lt;strong>演算法，就是解決問題的方法流程。&lt;/strong> *&lt;/p>
&lt;p>&lt;strong>Why do we need to learn algorithms?&lt;/strong>&lt;/p>
&lt;p>先講一下筆者的經歷：筆者當了7年多的工程師，當中有2.5年和Android kernel/HAL/framework相關，2年跟Android App和一般Software有關，後面則是ML/Deep Learning為主，在面試時也分別面過不同的職位，唯獨幾乎萬變不離其宗的，就是白板題。&lt;/p>
&lt;p>面試官拿出一道你見過或沒見過的題目，問你該怎麼解，&lt;br>
你思考後給出回答，並且討論可以改進的方式及可能的錯誤，&lt;br>
這應該是所有面試者都會歷經的流程。&lt;/p>
&lt;p>那麼，你是否經歷過這樣的狀況？&lt;/p>
&lt;p>&lt;em>「這個題目的類型看起來好眼熟，可是不知道從何下手，該怎麼辦 QQ」&lt;/em>&lt;/p>
&lt;p>白板題的重點，就在於&lt;strong>演算法&lt;/strong> 。掌握好演算法，就跟數學學會公式一樣，&lt;br>
可以將一些複雜的東西簡單化，平常練習的題目多了，&lt;br>
套起公式來自然得心應手，就算題目再怎麼變，也萬變不離其宗。&lt;/p>
&lt;p>當然，後面還會衍生出一個問題：一個題目該用哪種演算法比較好？&lt;br>
但這是另一個故事了，我們以後再談XD&lt;/p>
&lt;p>&lt;strong>Why LeetCode?&lt;/strong>&lt;/p>
&lt;p>那麼，現在網路上可以供作練習的網站相當之多，除了LeetCode外，&lt;br>
你可能還聽過HackerRank及CodeWar等，&lt;br>
那麼為什麼是用LeetCode而不是其他呢？&lt;/p>
&lt;p>以筆者的經驗，&lt;em>HackerRank&lt;/em>相當適合做為&lt;strong>熟悉語言特性使用&lt;/strong> ，但不適合目標是熟練解題的人。你可以在其 “LANGUAGE PROFICIENCY”的分類中針對特定的程式語言一路寫到尾，這樣可以對這個語言有一個比較基本的認識。&lt;br>
而雖然它們有”Interview Preparation Kit”的部分，但相對題目較為簡單，涵蓋範圍也較少。舉例來說，在Tree的分類上只有5題，這一點點的量，其實相當不足。同時，HackerRank的題目往往較長，限制也通常較多，(這裡是指Problem Solving分類)，和一般面試會遇到的題目型態較為不同。&lt;br>
但若今天的形式是給你&lt;strong>1個半小時解3題&lt;/strong> 的話，&lt;br>
那麼HackerRank的模式就會很適合你。&lt;/p>
&lt;p>Codewar的話，較為偏向打怪(題目)升級的模式，每個題目都會有一個等級，解決題目累積經驗值並提升自己的level會有一種練功的感覺。筆者不推薦的原因在於&lt;/p>
&lt;ol>
&lt;li>網站讀取速度偏慢 &lt;/li>
&lt;li>&lt;strong>題目沒有編號&lt;/strong> ，你會做到不知道哪裡去也不確定自己有沒有準備好XD &lt;/li>
&lt;li>Discuss區不像LeetCode傾向於分享整組解法&lt;/li>
&lt;/ol>
&lt;p>那LeetCode呢？&lt;br>
當前(2019/06/26)的題目量總共有1096題，Easy佔了當中的319題。&lt;br>
筆者練習的題目總量為348題: Easy 266, Medium 65, Hard 17。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-001.png"
width="351"
height="44"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-001_hu5b05f6b3fc84cc42a6b38786f5896c70_4473_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-001_hu5b05f6b3fc84cc42a6b38786f5896c70_4473_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="797"
data-flex-basis="1914px"
>&lt;/p>
&lt;p>2020/08/18:&lt;br>
當前的的題目量總共有1553題，Easy佔了當中的430題。&lt;br>
筆者練習的題目總量為502題: Easy 288, Medium 179, Hard 35。&lt;/p>
&lt;p>&lt;img src="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-002.png"
width="343"
height="53"
srcset="https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-002_hu3388a44216e7da0fa6d52503bb1db550_4570_480x0_resize_box_3.png 480w, https://learnwithdesolve.netlify.app/post/learn-algorithm-from-leetcode-0/image-002_hu3388a44216e7da0fa6d52503bb1db550_4570_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="647"
data-flex-basis="1553px"
>&lt;/p>
&lt;p>以筆者的個人經驗，只要將LeetCode的Easy難度寫過一輪，&lt;br>
搭上少量的Medium和些許的Hard題目，便足以應付絕大多數的白板題。&lt;br>
這當中要求的是盡可能不要去翻別人的答案，自己先兜出解法後，&lt;br>
在能力範圍內去盡力提升這個解的速度，&lt;br>
真的不行或卡超過半小時才去參考別人的解答。&lt;/p>
&lt;p>在練習到一般的白板題都不能難倒你後，就可以將注意力集中在你主要經驗相關的領域了。(如筆者找AI職缺，那麼就會偏向ML相關的知識)&lt;/p>
&lt;p>&lt;strong>What’s the plan?&lt;/strong>&lt;/p>
&lt;p>接下來的系列，將會以LeetCode從第1題開始順序往下，以Easy題目為主，參雜少量Medium題，搭配題目分析及演算法講解，在整理先前自我學習的過程中，希望能對大家有所幫助。解題所用的程式語言會以&lt;strong>Java&lt;/strong> 及&lt;strong>Python&lt;/strong> 為主，但概念基本上不會差多少，若是使用其他語言的朋友應該也可能從中理解思路。使用的解有些可能會因為我看到更好的解法，會使用其他人在Discuss區塊提出來的解，筆者會盡量標明是哪一位LeetCode user所寫的。&lt;/p>
&lt;p>除此以外，若文章中有錯字、寫錯或有任何讓人感到疑問的地方，&lt;br>
歡迎留言告訴我！&lt;/p>
&lt;p>&lt;strong>2020/09/05:&lt;/strong>&lt;br>
容筆者工商一下， &lt;strong>「從Leetcode學演算法｜進階篇」及&lt;/strong> 加贈的**「從Leetcode學演算法｜面試篇」已經全數上傳完囉！**&lt;/p>
&lt;p>目前只剩下給讀者的&lt;strong>進階篇+面試篇(3150)&lt;/strong> 和&lt;strong>全套同捆優惠(3990)&lt;/strong> 了QQ&lt;br>
「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
>https://bit.ly/leetcodeadv&lt;/a>&lt;br>
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠：&lt;br>
&lt;a class="link" href="https://bit.ly/leetcodeall" target="_blank" rel="noopener"
>https://bit.ly/leetcodeall&lt;/a>&lt;/p>
&lt;p>內容介紹：&lt;br>
這次選了40道難度加深的LeetCode題目，&lt;br>
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br>
同時這次購買進階篇的話，&lt;br>
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br>
當中包含了&lt;strong>面試準備須知分享&lt;/strong> ，&lt;strong>及訪談國內外不同經驗的工程師&lt;/strong> ，&lt;br>
讓你不論是&lt;strong>想走前端/後端/一般軟工&lt;/strong> 或者是&lt;strong>想找國外的工作&lt;/strong> ，&lt;br>
是&lt;strong>初學想轉職&lt;/strong> 還是&lt;strong>正在工作&lt;/strong> ，都能夠從中得到收穫呦！&lt;/p>
&lt;p>&lt;strong>PS. 因應建議，將文章目錄連結貼在底下，方便大家查找。&lt;br>
(請使用Ctrl+F輸入想要查找的題目或題型)&lt;/strong>&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-1-400da76b51b4" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 1&lt;/strong> &lt;/a>&lt;/p>
&lt;ol>
&lt;li>Two Sum (Easy)&lt;/li>
&lt;/ol>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-2-d4189f53018e" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 2&lt;/strong> &lt;/a>&lt;br>
0014. Longest Common Prefix (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-3-two-pointers-989b297ce5ac" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 3 Two Pointers&lt;/strong> &lt;/a>&lt;br>
0015. 3Sum (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-4-6a631eb50da3" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 4 Linked List (1)&lt;/strong> &lt;/a>&lt;br>
0021. Merge Two Sorted Lists (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-5-in-place-22d309007d15" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 5 In-Place&lt;/strong> &lt;/a>&lt;br>
0026. Remove Duplicates from Sorted Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 6 Binary Search&lt;/strong> &lt;/a>&lt;br>
0035. Search Insert Position (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-7-dynamic-programming-d1c3255dc266" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 7 Dynamic Programming (1)&lt;/strong> &lt;/a>&lt;br>
0053. Maximum Subarray (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-8-string-manipulation-1-6e01597f1e94" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 8 String Manipulation (1)&lt;/strong> &lt;/a>&lt;br>
0067. Add Binary (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-9-dynamic-programming-2-6d184d364960" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 9 Dynamic Programming (2)&lt;/strong> &lt;/a>&lt;br>
0070. Climbing Stairs (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-10-linked-list-2-8384845e8ad6" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 10 Linked List (2)&lt;/strong> &lt;/a>&lt;br>
0083. Remove Duplicates from Sorted List (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-11-bitwise-operation-1-3117c4ce925d" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 11 Bitwise Operation (1)&lt;/strong> &lt;/a>0089. Gray Code (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-12-linked-list-3-stack-1-f99d18e539a9" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 12 Linked List (3)/ Stack (1)&lt;/strong> &lt;/a>&lt;br>
0092. Reverse Linked List II (Medium)&lt;/p>
&lt;p>&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"
>&lt;strong>從LeetCode學演算法 - 13 Tree (1)&lt;/strong> &lt;/a>0100. Same Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-14-tree-2-queue-1-a992bc16d8f1" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 14 Tree (2) / Queue (1)&lt;/strong> &lt;/a>&lt;br>
0101. Symmetric Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-15-bitwise-operation-2-b3084a69698f" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 15 Bitwise Operation (2)&lt;/strong> &lt;/a>&lt;br>
0136. Single Number (Easy)&lt;/p>
&lt;p>&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" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 16 BST (1)&lt;/strong> &lt;/a>&lt;br>
0098. Validate Binary Search Tree (Medium)&lt;/p>
&lt;p>&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" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 17 Tree (3)&lt;/strong> &lt;/a>&lt;br>
0094. Binary Tree Inorder Traversal (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-18-tree-4-3f23e856c2f7" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 18 Tree (4)&lt;/strong> &lt;/a>&lt;br>
0124. Binary Tree Maximum Path Sum (Hard)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-19-56aaed4849c5" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 19 Tree (5)&lt;/strong> &lt;/a>&lt;br>
0111. Minimum Depth of Binary Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-20-tree-6-e08dedd83656" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 20 Tree (6)&lt;/strong> &lt;/a>&lt;br>
0110. Balanced Binary Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-21-dynamic-programming-3-6c6a405d1526" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 21 Dynamic Programming (3)&lt;/strong> &lt;/a>&lt;br>
0062. Unique Paths (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-22-array-1-9b7b12893d75?source=friends_link&amp;amp;sk=10994c995bf198744ef232104b6d6775" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 22 Array (1)&lt;/strong> &lt;/a>&lt;br>
0169. Majority Element (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-23-array-2-ed53a5f7d086?source=friends_link&amp;amp;sk=fbcac36ea706060513d9c3e72d40fc96" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 23 Array (2)&lt;/strong> &lt;/a>&lt;br>
0229. Majority Element II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-24-dynamic-programming-4-5b278c8bc317?source=friends_link&amp;amp;sk=ece62f392952131c8ad716c1a690b4ac" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 24 Dynamic Programming (4)&lt;/strong> &lt;/a>&lt;br>
0063. Unique Paths II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-25-array-3-bca3bca74ca2?source=friends_link&amp;amp;sk=2b26f2e316bbfd7bc96ff372259e652a" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 25 Array (3):&lt;/strong> &lt;/a>&lt;br>
0283. Move Zeroes (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-26-dynamic-programming-5-75fad660933d?source=friends_link&amp;amp;sk=5a1f7a493fde3442bdfc8bdf4ca33ca5" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 26 Dynamic Programming (5)&lt;/strong> &lt;/a>&lt;br>
0096. Unique Binary Search Trees (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-27-array-4-c5af0d3265e9?source=friends_link&amp;amp;sk=0218b8d3a3878810a7389f4f7751c01d" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 27 Array (4)&lt;/strong> &lt;/a>&lt;br>
0189. Rotate Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-28-dynamic-programming-6-8e5a81a8437d?source=friends_link&amp;amp;sk=d87bd13d5e6a85da75c83222cddc0d60" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 28 Dynamic Programming (6)&lt;/strong> &lt;/a>&lt;br>
0198. House Robber (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-29-dynamic-programming-7-8e3aedb07ca3?source=friends_link&amp;amp;sk=b9b2fb6d14b84c4c122c89f71ccf9979" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 29 Dynamic Programming (7)&lt;/strong> &lt;/a>&lt;br>
0213. House Robber II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-30-tree-7-bc71ac3a759a?source=friends_link&amp;amp;sk=803ebae93cd8a1b8de4762a66e5d21c8" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 30 Tree (7)&lt;/strong> &lt;/a>&lt;br>
0144. Binary Tree Preorder Traversal (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-31-linked-list-4-4c704607581d?source=friends_link&amp;amp;sk=79194184099bb3889740a28c454af48c" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 31 Linked List (4)&lt;/strong> &lt;/a>&lt;br>
0141. Linked List Cycle (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-32-bst-2-7a731f9a7855?source=friends_link&amp;amp;sk=ed070345134c07e48a7afff7d19a526f" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 32 BST (2)&lt;/strong> &lt;/a>&lt;br>
0700. Search in a Binary Search Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-33-array-5-7b3c5f6b4aa9?source=friends_link&amp;amp;sk=60e3bd48797ae082720a545faf654d51" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 33 Array (5)&lt;/strong> &lt;/a>&lt;br>
0905. Sort Array By Parity (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-34-array-6-97e6d3a9a055?source=friends_link&amp;amp;sk=bff8b66f3ceefe562f1a93b54281add6" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 34 Array (6)&lt;/strong> &lt;/a>&lt;br>
0977. Squares of a Sorted Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-35-bst-3-b1f225f39aa3?source=friends_link&amp;amp;sk=1f7a93de4a479eb1d3827ba2b8c884e7" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 35 BST (3)&lt;/strong> &lt;/a>&lt;br>
0108. Convert Sorted Array to Binary Search Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-36-merge-sort-1-21dde785b0df?source=friends_link&amp;amp;sk=df2e91f82ce0fe4fb91c6866e87549dc" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 36 Merge Sort (1)&lt;/strong> &lt;/a>&lt;br>
0148. Sort List (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-37-dynamic-programming-8-f60ad427d76d?source=friends_link&amp;amp;sk=4801f1ff8060bc5d3771f74e71dc8b1c" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 37 Dynamic Programming (8)&lt;/strong> &lt;/a>&lt;br>
0121. Best Time to Buy and Sell Stock (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-38-array-7-ab9b0740a048?source=friends_link&amp;amp;sk=f7efd443991b61c0d4daa6fe8595cd06" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 38 Array (7)&lt;/strong> &lt;/a>&lt;br>
0088. Merge Sorted Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-39-array-8-hash-table-1-89fa9bd2832d?sk=917a595b0687f84474a6bd93bb3e414b" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 39 Array (8) / Hash Table (1)&lt;/strong> &lt;/a>&lt;br>
1160. Find Words That Can Be Formed by Characters (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-40-array-9-48a6b5a8c3a4?sk=bcb77edf50990fd862948996472fd8a0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 40 Array (9)&lt;/strong> &lt;/a>&lt;br>
0238. Product of Array Except Self (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-41-hash-table-2-944fd5db94d?sk=d7b50babd8ee1cace590d769467a97f0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 41 Hash Table (2)&lt;/strong> &lt;/a>&lt;br>
0242. Valid Anagram (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-42-backtracking-1-tree-8-2f230ef087cd?sk=55c3770b3626f512e1d1a2477f91e3a0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 42 Backtracking (1) / Tree (8)&lt;/strong> &lt;/a>&lt;br>
0257. Binary Tree Paths (Easy)&lt;/p>
&lt;p>&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?sk=0db81ed4dcf2f7e4b93c7935b3f24a3a" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 43 BFS (1) / Queue (2)&lt;/strong> &lt;/a>&lt;br>
1161. Maximum Level Sum of a Binary Tree (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-44-linked-list-5-7f9f333dec22?sk=ed63b6656a5986babeed1adfdb14aeb7" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 44 Linked List (5)&lt;/strong> &lt;/a>&lt;br>
0160. Intersection of Two Linked Lists (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-45-dfs-1-a59fa98f948d?sk=146ad95c3e8ea8ea03efda51117cbaba" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 45 DFS (1)&lt;/strong> &lt;/a>&lt;br>
0200. Number of Islands (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-46-bfs-2-queue-3-8d95a7e1a187?sk=3edf05b3be410512085073d01d00e91e" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 46 BFS (2) / Queue (3)&lt;/strong> &lt;/a>&lt;br>
0199. Binary Tree Right Side View (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-47-array-10-35a2c22505cd?sk=04a11fa52a96fcc85014d1f4caa0b8f8" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 47 Array (10)&lt;/strong> &lt;/a>&lt;br>
0204. Count Primes (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-48-trie-1-533ffdfdc6ac?sk=26fa104e4af5aa5f8bbd986bb756a759" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 48 Trie (1)&lt;/strong> &lt;/a>&lt;br>
0819. Most Common Word (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-49-hash-table-3-5600b466535a?sk=bc92bfd1c987592ba12afa2b5e6e7c4a" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 49 Hash Table (3)&lt;/strong> &lt;/a>&lt;br>
0217. Contains Duplicate (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-50-tree-9-90a07b686fe2?sk=284d0da4f5528a90b254e040ec31f13c" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 50 Tree (9)&lt;/strong> &lt;/a>&lt;br>
0226. Invert Binary Tree (Easy)&lt;/p>
&lt;p>&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?sk=cf255d1679a1e6eb4a094c577bded568" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 51 BST (4)&lt;/strong> &lt;/a>&lt;br>
0235. Lowest Common Ancestor of a Binary Search Tree (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-52-array-11-888b1df60c18?sk=9364474de6ca8176a3af0446beb034fd" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 52 Array (11)&lt;/strong> &lt;/a>&lt;br>
0268. Missing Number (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-53-binary-search-2-511bb50fb641?sk=7a2dcab9af1d0bf5ea6988f8f64a03cc" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 53 Binary Search (2)&lt;/strong> &lt;/a>&lt;br>
0278. First Bad Version (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-54-dfs-2-ba5c9e731bb8?sk=b321422c2316ed898d1779e78471d230" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 54 DFS (2)&lt;/strong> &lt;/a>&lt;br>
0114. Flatten Binary Tree to Linked List (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-55-dfs-3-26306bc5a084?sk=2d24b67dee69e8262e108e8bc745c56b" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 55 DFS (3)&lt;/strong> &lt;/a>&lt;br>
0236. Lowest Common Ancestor of a Binary Tree (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-56-binary-search-3-bd76049f8765?sk=9839faa7bfcc119a10b7fbbe6f40a6df" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 56 Binary Search (3)&lt;/strong> &lt;/a>&lt;br>
0240. Search a 2D Matrix II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-57-binary-search-4-ed90971a3cd8?sk=7a24b34375bd7c49a91d47702a039afe" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 57 Binary Search (4)&lt;/strong> &lt;/a>&lt;br>
0074. Search a 2D Matrix (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-58-two-pointer-2-5874fc7892e5?sk=dac3d94a58c1523a754d8d40f821c17d" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 58 Two Pointer (2)&lt;/strong> &lt;/a>&lt;br>
0075. Sort Colors (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-59-backtracking-2-dfs-4-8b242c54515f?sk=a9a847650fe993529968b6679bd2fc4e" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 59 Backtracking (2) / DFS (4)&lt;/strong> &lt;/a>&lt;br>
0079. Word Search (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-60-backtracking-3-dfs-5-ccc679dfa407?sk=22adb6368aa9fbc5fbf7a2d15d1c5445" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 60 Backtracking (3) / DFS (5)&lt;/strong> &lt;/a>&lt;br>
0078. Subsets (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-61-dynamic-programming-9-784b21b36c47?sk=5ef10c13e32c0b2dcf6e25420b7f7141" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 61 Dynamic Programming (9)&lt;/strong> &lt;/a>&lt;br>
1140. Stone Game II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-62-tree-10-3c9b17f7b68f?sk=9862ac05cea3e74035cd56ca845f09ae" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 62 Tree (10)&lt;/strong> &lt;/a>&lt;br>
0102. Binary Tree Level Order Traversal (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-63-backtracking-4-dfs-6-43262d937bab?sk=054c9a7ce6421fd48beb44390a2368ab" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 63 Backtracking (4) / DFS (6)&lt;/strong> &lt;/a>&lt;br>
0077. Combinations (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-64-array-12-two-pointer-3-94142305c49a?sk=b4bc4e3060aeb757b88be4db438302a5" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 64 Array (12) / Two Pointer (3)&lt;/strong> &lt;/a>&lt;br>
0080. Remove Duplicates from Sorted Array II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-65-array-13-cf15503c77e2?source=friends_link&amp;amp;sk=a3a59cb69ee68ee8822fa8fff51cb7e2" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 65 Array (13)&lt;/strong> &lt;/a>&lt;br>
0926. Flip String to Monotone Increasing (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-66-bitwise-operation-3-736d10f7acaf?sk=52f2ebda54b5a6f256a8801d52aca404" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 66 Bitwise Operation (3)&lt;/strong> &lt;/a>&lt;br>
0190. Reverse Bits (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-67-bitwise-operation-4-9dbe975e1959?sk=d203a23ee02aee39341dbededd415f9f" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 67 Bitwise Operation (4)&lt;/strong> &lt;/a>&lt;br>
0191. Number of 1 Bits (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-68-bitwise-operation-5-51ec306d547b?sk=82d6611cc384880258e4274ec7d511b0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 68 Bitwise Operation (5)&lt;/strong> &lt;/a>&lt;br>
0201. Bitwise AND of Numbers Range (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-69-hash-set-1-1930c3a0db5?sk=d56d79c38780e7f1424fddcc34d18ab9" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 69 Hash Set (1)&lt;/strong> &lt;/a>&lt;br>
0202. Happy Number (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-70-linked-list-6-c42d1c7f0a4e?sk=e395976b377984b71dfaaca49838845f" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 70 Linked List (6)&lt;/strong> &lt;/a>&lt;br>
0203. Remove Linked List Elements (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-71-hash-table-4-565891ce80a6?sk=593c987ce99d2c8745ad75ea0eca0669" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 71 Hash Table (4)&lt;/strong> &lt;/a>&lt;br>
0205. Isomorphic Strings (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-72-linked-list-7-419253aa3a9a?source=friends_link&amp;amp;sk=5cd0fea352aeb31b56fb54c6bc2bb084" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 72 Linked List (7)&lt;/strong> &lt;/a>&lt;br>
0206. Reverse Linked List (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-74-linked-list-8-27c4894da297?source=friends_link&amp;amp;sk=e3a87397e807007fdcd1acfb3a95f5d5" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 74 Linked List (8)&lt;/strong> &lt;/a>&lt;br>
0234. Palindrome Linked List (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-75-array-14-85bab85fffd5?source=friends_link&amp;amp;sk=53017029e527caa8c2b51343bfc4bbf1" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 75 Array (14)&lt;/strong> &lt;/a>&lt;br>
0289. Game of Life (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-76-hash-table-5-c22fba2bffa?source=friends_link&amp;amp;sk=248b6c6a18e6e0b48874787008537966" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 76 Hash Table (5)&lt;/strong> &lt;/a>&lt;br>
0290. Word Pattern (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-77-string-2-25a3b04378d7?source=friends_link&amp;amp;sk=0bb898c391ecd0baa174b59df410b192" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 77 String (2)&lt;/strong> &lt;/a>&lt;br>
1071. Greatest Common Divisor of Strings (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-78-two-pointer-4-binary-search-5-49e21e35d2a5?source=friends_link&amp;amp;sk=c5f0ce4cc846957ea59d8b49868dfa57" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 78 Two Pointer (4) / Binary Search(5)&lt;/strong> &lt;/a>&lt;br>
0392. Is Subsequence (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-79-hash-table-6-a4fe408959d5?source=friends_link&amp;amp;sk=d9b1f69f777f566fa1d701725f391813" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 79 Hash Table (6)&lt;/strong> &lt;/a>&lt;br>
0383. Ransom Note (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-80-linked-list-9-c0902d8f609a?source=friends_link&amp;amp;sk=5120ed404264b1561d8f681a923eb1d6" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 80 Linked List (9)&lt;/strong> &lt;/a>&lt;br>
0082. Remove Duplicates from Sorted List II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-81-backtracking-5-dfs-7-8c82648a5f43?source=friends_link&amp;amp;sk=c4dcec3c3c873e02e8222944b4febb53" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 81 Backtracking (5) / DFS (7)&lt;/strong> &lt;/a>&lt;br>
0093. Restore IP Addresses (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-82-linked-list-10-800f7a161809?source=friends_link&amp;amp;sk=8e038b3536f435b7900dac3812791073" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 82 Linked List (10)&lt;/strong> &lt;/a>&lt;br>
0086. Partition List (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-83-dynamic-programming-10-712b198c07cb?source=friends_link&amp;amp;sk=c7677c04504f42f6a1a0af60a7db84c6" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 83 Dynamic Programming (10)&lt;/strong> &lt;/a>&lt;br>
0091. Decode Ways (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-84-tree-11-dfs-8-2bebed74524d?source=friends_link&amp;amp;sk=85c9a24c296842637190775ba0f49612" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 84 Tree (11) / DFS (8)&lt;/strong> &lt;/a>&lt;br>
0116. Populating Next Right Pointers in Each Node (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-85-string-3-7556d2f4cf7d?source=friends_link&amp;amp;sk=5d5af2c38d0bcd087d892d7b06546ed3" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 85 String (3)&lt;/strong> &lt;/a>&lt;br>
1332. Remove Palindromic Subsequences (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-86-hash-table-7-811abd9dbef5?source=friends_link&amp;amp;sk=36fd20a44014b89ec04aa92f6e03921b" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 86 Hash Table (7)&lt;/strong> &lt;/a>&lt;br>
1331. Rank Transform of an Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-87-bitwise-operation-6-c464dc5975d7?source=friends_link&amp;amp;sk=f2ce8f85b2c097aa8434a9f9272137b0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 87 Bitwise Operation (6)&lt;/strong> &lt;/a>&lt;br>
1342. Number of Steps to Reduce a Number to Zero (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-88-hash-table-8-78aa848efa54?source=friends_link&amp;amp;sk=3e2b04a86a8269b12c88730bf0a6c817" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 88 Hash Table (8)&lt;/strong> &lt;/a>&lt;br>
0575. Distribute Candies (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-89-hashtable-9-2dc0f33a97c4?source=friends_link&amp;amp;sk=6fd220ccd806d994de85a5ac8ec676fd" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 89 HashTable (9)&lt;/strong> &lt;/a>&lt;br>
1346. Check If N and Its Double Exist (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-90-dynamic-programming-11-dfs-9-e61804f3ef6d?source=friends_link&amp;amp;sk=ae1e7bfeea8fb26c57b7195d83e5408c" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 90 Dynamic Programming (11) / DFS (9)&lt;/strong> &lt;/a>&lt;br>
0576. Out of Boundary Paths (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-91-string-4-f1b8c773af37?source=friends_link&amp;amp;sk=dfac6c1143f749d7f9d399f933b06052" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 91 String (4)&lt;/strong> &lt;/a>&lt;br>
0678. Valid Parenthesis String (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-92-string-5-da5d823ff350?source=friends_link&amp;amp;sk=f6a489cf0ba2924c4cf6f02d0f1794d4" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 92 String (5)&lt;/strong> &lt;/a>&lt;br>
0680. Valid Palindrome II (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-93-tree-12-dfs-9-c37d54d31a2d?source=friends_link&amp;amp;sk=836c951c7973cf0e9b55826a93793a54" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 93 Tree (12) / DFS (9)&lt;/strong> &lt;/a>&lt;br>
0687. Longest Univalue Path (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-94-hash-table-10-97cd8f9ec1de?source=friends_link&amp;amp;sk=6db40946236a6eaef872056d1d141812" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 94 Hash Table (10)&lt;/strong> &lt;/a>&lt;br>
0438. Find All Anagrams in a String (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-95-dynamic-programming-12-d7d73cb9c73c?source=friends_link&amp;amp;sk=34fde6e2cfd30079ebaa08da8e1fbdda" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 95 Dynamic Programming (12)&lt;/strong> &lt;/a>&lt;br>
1143. Longest Common Subsequence (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-96-bst-5-dfs-10-df97cee58987?source=friends_link&amp;amp;sk=be23cf67425348e0dd109fc0508de8ed" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 96 BST (5)&lt;/strong> &lt;/a>&lt;br>
1008. Construct Binary Search Tree from Preorder Traversal (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-97-dynamic-programming-13-cb0c17e435?source=friends_link&amp;amp;sk=19f82bd7dfe248b308c17c0a6c2e2420" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 97 Dynamic Programming (13)&lt;/strong> &lt;/a>&lt;br>
0368. Largest Divisible Subset (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-98-tree-13-dfs-10-3392102383ab?source=friends_link&amp;amp;sk=abcd4360408fd87901be049efbdfc528" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 98 Tree (13) / DFS (10)&lt;/strong> &lt;/a>&lt;br>
0129. Sum Root to Leaf Numbers (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-99-tree-14-dfs-11-801d2c311ad4?source=friends_link&amp;amp;sk=beaa292cacca27021c981be02eb07212" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 99 Tree (14) / DFS (11)&lt;/strong> &lt;/a>&lt;br>
0404. Sum of Left Leaves (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-100-dynamic-programming-14-c98b2950080?source=friends_link&amp;amp;sk=ab6301a3e05a9abad42cd8eb9823fbb6" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 100 Dynamic Programming (14)&lt;/strong> &lt;/a>&lt;br>
1510. Stone Game IV (Hard)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-101-string-6-5a8387998957?source=friends_link&amp;amp;sk=013e572dca767101a3c8f82039c2bc2e" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 101 String (6)&lt;/strong> &lt;/a>&lt;br>
1529. Bulb Switcher IV (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-102-tree-15-dfs-12-e489f3c69986?source=friends_link&amp;amp;sk=5cbbb13df3879ce2cffcf857f6a8f828" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 102 Tree (15) / DFS (12)&lt;/strong> &lt;/a>&lt;br>
1530. Number of Good Leaf Nodes Pairs (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-103-tree-16-dfs-13-bfs-3-queue-4-a9ccd4e8d007?source=friends_link&amp;amp;sk=c4917c50f035715b1aa428b3b8fc0459" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 103 Tree (16) / DFS (13) / BFS (3) / Queue (4)&lt;/strong> &lt;/a>&lt;br>
0112. Path Sum (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-104-tree-17-dfs-14-backtracking-6-1573c8c4f0eb" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 104 Tree (17) / DFS (14) / Backtracking (6)&lt;/strong> &lt;/a>&lt;br>
0113. Path Sum II (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-105-tree-18-dfs-15-backtracking-7-553cede486f4?source=friends_link&amp;amp;sk=5839a79d83be4e05294b92bd180f26d8" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 105 Tree (18) / DFS (15) / Backtracking (7)&lt;/strong> &lt;/a>&lt;br>
0437. Path Sum III (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-106-tree-19-dfs-16-8a362a0b51f8?sk=82dbb0390d1ae9b74f77cd77a8eca5f0" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 106 Tree (19) / DFS (16)&lt;/strong> &lt;/a>&lt;br>
0563. Binary Tree Tilt (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-107-string-7-stack-2-9d27d3769cb?sk=0758cffe64a84caf299fd7aa3da9f6de" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 107 String (7) / Stack (2)&lt;/strong> &lt;/a>&lt;br>
1544. Make The String Great (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-108-tree-20-dfs-17-c92f6168982b?sk=7ca90177d7ba6b026a0c913d39b09220" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 108 Tree (20) / DFS (17)&lt;/strong> &lt;/a>&lt;br>
1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-109-array-15-hash-table-11-b9301b632d80?sk=9422c700151fe6e1c581477c64f7863d" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 109 Array (15) / Hash Table (11)&lt;/strong> &lt;/a>&lt;br>
1640. Check Array Formation Through Concatenation (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-110-array-16-greedy-algorithm-1-29e653bd4075?sk=d55a1ef4eecd6fa0bd8ba77d292fa6d5" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 110 Array (16) / Greedy Algorithm (1)&lt;/strong> &lt;/a>&lt;br>
0881. Boats to Save People (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-111-dfs-18-backtracking-8-19ec2666d8e8?sk=f7356ae0b6609254d1782e84853e63e2" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 111 DFS (18) / Backtracking (8)&lt;/strong> &lt;/a>&lt;br>
0784. Letter Case Permutation (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-112-binary-search-6-newtons-method-797b6bed7c5a?sk=03b5dceb458eff27303ee7271a048145" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 112 Binary Search (6) / Newton’s Method&lt;/strong> &lt;/a>&lt;br>
0367. Valid Perfect Square (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-113-bfs-4-queue-5-4d9f53579e63?sk=0cc9c9a284eec3ffd861d4d696247da7" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 113 BFS (4) / Queue (5)&lt;/strong> &lt;/a>&lt;br>
1091. Shortest Path in Binary Matrix (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-114-stack-3-cba39eaece38?sk=28b48eb1fc692577fd18845a819920ca" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 114 Stack (3)&lt;/strong> &lt;/a>&lt;br>
0946. Validate Stack Sequences (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/3616ad4a6496?sk=5a3ff34550871f5fc2b33a9023853ef3" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 115 Graph(1) / Union Find (1)&lt;/strong> &lt;/a>&lt;br>
0684. Redundant Connection (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/d065458977bd?sk=1a37422aeadeb683bffc8791ae1acdef" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 116 Tree (21) / DFS (19)&lt;/strong> &lt;/a>&lt;br>
0814. Binary Tree Pruning (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-117-array-17-a2ce7111af60?sk=1d3147ef33595d2cfb97f6d9933b3822" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 117 Array (17)&lt;/strong> &lt;/a>&lt;br>
0941. Valid Mountain Array (Easy)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-118-dfs-20-bfs-5-queue-6-cba39cf9a945?sk=74cc1af0e57c9c72e966a085f13f1be4" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 118 DFS (20) /BFS (5) / Queue (6)&lt;/strong> &lt;/a>&lt;br>
0934. Shortest Bridge (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-119-graph-2-dfs-21-4fb697ef5f8b?sk=1c90046ada270bc21b2d605f11e73bbe" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法 - 119 Graph (2) / DFS (21)&lt;/strong> &lt;/a>&lt;br>
0797. All Paths From Source to Target (Medium)&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-120-0547-number-of-provinces-f9e473797ba7?sk=7b3b78756a822a70ba403d1cbb0cc156" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法-120 (0547. Number of Provinces)&lt;/strong> &lt;/a>&lt;br>
Categories: Graph/Union Find, Level: Medium&lt;br>
English Version: &lt;a class="link" href="https://desolve.medium.com/51a78df0670c" target="_blank" rel="noopener"
>https://desolve.medium.com/51a78df0670c&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://desolve.medium.com/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-121-0802-find-eventual-safe-states-9e5dc3eb368e?sk=97c209fcfa6e643b7419f4405dcc499d" target="_blank" rel="noopener"
>&lt;strong>從LeetCode學演算法-121 (0802. Find Eventual Safe States)&lt;/strong> &lt;/a>&lt;br>
Categories: Graph/DFS, Level: Medium&lt;br>
English Version: &lt;a class="link" href="https://desolve.medium.com/b3b88410d561" target="_blank" rel="noopener"
>https://desolve.medium.com/b3b88410d561&lt;/a>&lt;/p></description></item></channel></rss>