<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Two Pointer on 跟著 Desolve 學程式</title><link>https://desolve.pages.dev/tags/two-pointer/</link><description>Recent content in Two Pointer on 跟著 Desolve 學程式</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Sat, 28 Dec 2019 00:00:00 +0800</lastBuildDate><atom:link href="https://desolve.pages.dev/tags/two-pointer/index.xml" rel="self" type="application/rss+xml"/><item><title>從LeetCode學演算法 - 78 Two Pointer (4) / Binary Search (5)</title><link>https://desolve.pages.dev/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://desolve.pages.dev/post/learn-algorithm-from-leetcode-78-two-pointer-4-binary-search-5/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 78 Two Pointer (4) / Binary Search (5)" /&gt;&lt;p&gt;&lt;strong&gt;0392. Is Subsequence (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a string &lt;strong&gt;s&lt;/strong&gt; and a string ** t**, check if ** s** is a subsequence of ** t**.&lt;/p&gt;
&lt;p&gt;You may assume that there are only lower case English letters in both &lt;strong&gt;s&lt;/strong&gt; and ** t**. ** t** is potentially a very long (length ~= 500,000) string, and ** s** is a short string (&amp;lt;=100).&lt;/p&gt;
&lt;p&gt;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&gt;&amp;quot;ace&amp;quot;&lt;/code&gt; is a subsequence of &lt;code&gt;&amp;quot;abcde&amp;quot;&lt;/code&gt; while &lt;code&gt;&amp;quot;aec&amp;quot;&lt;/code&gt; is not).&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;s&lt;/strong&gt; = &lt;code&gt;&amp;quot;abc&amp;quot;&lt;/code&gt;, ** t** = &lt;code&gt;&amp;quot;ahbgdc&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Return &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;s&lt;/strong&gt; = &lt;code&gt;&amp;quot;axc&amp;quot;&lt;/code&gt;, ** t** = &lt;code&gt;&amp;quot;ahbgdc&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Return &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt;&lt;br&gt;
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&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個字串s跟一個字串t，&lt;br&gt;
檢查s是否是t的subsequence(子序列)。可以假設s是一個短字串(長度≤100)且t是一個長字串(長度約500000)。&lt;/p&gt;
&lt;p&gt;從原字串t刪除字母(也可以完全不刪)，&lt;br&gt;
並保有原字串的相對位置，所構成的新字串，即為t的子序列。&lt;br&gt;
後面有一個Follow up問的是，&lt;br&gt;
假設這個函式會拿來檢查很多次(k次)不同的S的話(例如會處理1billion次)，&lt;br&gt;
要怎麼實作這個函式比較好？&lt;/p&gt;
&lt;p&gt;首先我們先來看看比較直觀的解法。&lt;br&gt;
我們先舉個例子，如果有一個s是”abcde”的話，&lt;br&gt;
s要是t的子序列的條件，就是我們要能在t當中，&lt;br&gt;
&lt;strong&gt;依序得到&lt;/strong&gt; a~e這五個字母。&lt;br&gt;
那麼第一個我們一定要先找a，假設從t中找到一個a以後，&lt;br&gt;
按照順序的話，&lt;strong&gt;這個a以前的bcde就都不能用了&lt;/strong&gt; ！&lt;br&gt;
(因為順序就不對啦XD)&lt;br&gt;
同樣的，找到b以後b以前的cde也不能用，以此類推。&lt;br&gt;
因此，我們要保持能確定找到可能性的方式，&lt;br&gt;
就是&lt;strong&gt;每一次在t中都取這個順序最前面出現的字母&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;在s當中使用一個記錄index用的&lt;strong&gt;i&lt;/strong&gt; ，&lt;br&gt;
從頭開始&lt;strong&gt;找t中的s[i]&lt;/strong&gt; 在哪，記錄為&lt;strong&gt;pre&lt;/strong&gt; 。&lt;br&gt;
每次找到以後，&lt;strong&gt;將i遞增&lt;/strong&gt; ，&lt;br&gt;
接下來從&lt;strong&gt;t的pre+1處&lt;/strong&gt; 開始尋找下一個s[i]的位置。&lt;br&gt;
如果找不到的話呢？就表示沒辦法成立，應該回傳false，&lt;br&gt;
否則當全部的s的字母都能找到對應的位置的話，&lt;br&gt;
則代表s可以作為t的子序列。&lt;/p&gt;
&lt;p&gt;上面描述這樣的方法，我們使用了兩個索引值，&lt;br&gt;
來記錄s和t當前查找到的位置，&lt;br&gt;
所以這個解法可以視為two pointer手段的一種操作。&lt;/p&gt;
&lt;p&gt;同時，我們前面在解的時候，&lt;br&gt;
每次都&lt;strong&gt;盡可能&lt;/strong&gt; 去找&lt;strong&gt;最前面出現&lt;/strong&gt; 的第一個s[i]，&lt;br&gt;
這種概念的想法，僅在特定的題目適用。&lt;br&gt;
當符合在&lt;strong&gt;每一個當前狀況都取當前最佳的狀況&lt;/strong&gt; ，&lt;br&gt;
&lt;strong&gt;全局就會是最佳&lt;/strong&gt; 的時候，我們就在局部的區段盡可能貪婪。&lt;br&gt;
這樣子的策略被稱為&lt;strong&gt;貪婪演算法&lt;/strong&gt; (Greedy Algorithm)&lt;/p&gt;
&lt;p&gt;請留意到，這種方式往往在很多情況下會失效，&lt;br&gt;
所以在使用前請詳閱公開說明書(X)。&lt;br&gt;
(開玩笑的XD，應該是&lt;strong&gt;使用前請確認局部最佳能推導至全局最佳&lt;/strong&gt; 。)&lt;/p&gt;
&lt;p&gt;這麼做基本上要掃過s跟t的字串，所以時間會是O(len(s)+len(t))，&lt;br&gt;
或者說當t遠大於s的時候可以視為O(len(t))。&lt;/p&gt;
&lt;p&gt;那麼如果搭配Follow up的條件呢？&lt;br&gt;
如果有k次不同的s的檢查，&lt;br&gt;
就上面的解法而言，每次仍然要各掃過一遍s跟t，&lt;br&gt;
時間複雜度是&lt;strong&gt;O(k*(len(s)+len(t)))&lt;/strong&gt; ，顯然當t很大的時候，&lt;br&gt;
掃過k次是很不理想的，我們會希望能夠化簡一點這個部分。&lt;/p&gt;
&lt;p&gt;那要怎麼作呢？這邊引用&lt;strong&gt;shuoshankou&lt;/strong&gt; 在leetcode上的解，&lt;br&gt;
我們可以先&lt;strong&gt;針對t建立一個HashMap&lt;/strong&gt; ，當中的&lt;strong&gt;key是t上的字母&lt;/strong&gt; ，&lt;br&gt;
而&lt;strong&gt;value是這個字母出現在t上面的indices&lt;/strong&gt; (使用ArrayList來儲存)。&lt;br&gt;
這個儲存過程會是&lt;strong&gt;O(len(t))&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;接著要查找的過程就會變成&lt;strong&gt;針對s[i]來搜尋HashMap上的index，&lt;br&gt;
且限定這個index要剛好是在i之後的第一個出現的位置。&lt;strong&gt;有沒有覺得很眼熟？沒錯，&lt;/strong&gt; 這不就是Binary Search嗎&lt;/strong&gt;？&lt;br&gt;
我們在處理的，就跟對於某個陣列，&lt;br&gt;
搜尋一個值在哪裡(或應插入在哪裡)的問題一樣！&lt;/p&gt;
&lt;p&gt;所以就一般來說，搜尋需求是log(N)，&lt;br&gt;
如果前後拆成常數的單位可以忽略不記，&lt;br&gt;
所以對於k個s搜尋所需會是&lt;strong&gt;O(k*len(s) * log(len(t)))&lt;/strong&gt; ，&lt;br&gt;
當k大到一定程度的時候，顯然只作一次O(len(t))先建立對應表，&lt;br&gt;
讓後面的&lt;strong&gt;搜尋相關的t的複雜度都變成對數量級&lt;/strong&gt; 是相當划算的。&lt;/p&gt;
&lt;p&gt;注意，以這題的測試資料而言，Binary Search速度並不會跑起來比較漂亮，&lt;br&gt;
原因是測試資料的總數可能相對有限，並不像Follow up假想那樣，&lt;br&gt;
所以前面吃下一整個建立HashMap的時間就會顯得拖累。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;p&gt;Java的部分可以先檢查s和t的長度來避免一些根本不需要跑的狀況，&lt;br&gt;
同時使用&lt;strong&gt;indexOf&lt;/strong&gt; 來搜尋每次的si第一個出現的位置。&lt;br&gt;
(&lt;strong&gt;搜尋不到的話indexOf會回傳-1&lt;/strong&gt; )&lt;/p&gt;
&lt;p&gt;Binary Search的寫法則如註解處，&lt;br&gt;
先建立起HashMap並掃過整個t並依序塞入，&lt;br&gt;
後面再使用getNextIndex來寫Binary Search。&lt;br&gt;
其實如果要能像Follow up那樣反覆利用的話，&lt;br&gt;
應該要能將t的輸入抽離開來，題目的要求和預設寫法並沒有考慮這點，&lt;br&gt;
會導致每次都需要對t建立一個HashMap。&lt;/p&gt;
&lt;p&gt;如果要重複利用的話，應該要給定成class Solution的變數，&lt;br&gt;
且建立時能先給入t才對。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/455f2c972c9c7f23ac66c831e013cd03.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python的部分則使用&lt;strong&gt;index&lt;/strong&gt; 來進行查找，&lt;br&gt;
請留意查找不到的話會產生exception，&lt;br&gt;
所以這邊是使用&lt;strong&gt;try/except&lt;/strong&gt; 來處理的。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/075cf41436103c259d2b37f3bccd4c41.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(請見上面詳述。)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;感謝大家對這系列文章的支持！這邊跟大家自我工商一下：&lt;/p&gt;
&lt;p&gt;筆者開設的系列同名線上課程：&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜基礎篇」已經上線啦！&lt;/strong&gt; 在這堂課中，你將學會利用十種演算法/資料結構來優化解題過程，&lt;br&gt;
並實際完整練習&lt;strong&gt;20題&lt;/strong&gt; 精選考古題，&lt;br&gt;
進而逐漸提升到不需提示也可以突破白板題，取得工作門票！&lt;br&gt;
&lt;strong&gt;Medium優惠(接下來快要漲成下個價格啦XD)：&lt;/strong&gt; &lt;a class="link" href="https://hiskio.com/courses/319?promo_code=VEQZV7E" target="_blank" rel="noopener"
&gt;&lt;strong&gt;https://hiskio.com/courses/319?promo_code=VEQZV7E&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 64 Array (12) / Two Pointer (3)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-64-array-12-two-pointer-3/</link><pubDate>Tue, 22 Oct 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-64-array-12-two-pointer-3/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 64 Array (12) / Two Pointer (3)" /&gt;&lt;p&gt;&lt;strong&gt;0080. Remove Duplicates from Sorted Array II (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a sorted array &lt;em&gt;nums&lt;/em&gt;, remove the duplicates &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
&gt;&lt;strong&gt;in-place&lt;/strong&gt; &lt;/a&gt; such that duplicates appeared at most &lt;em&gt;twice&lt;/em&gt; and return the new length.&lt;/p&gt;
&lt;p&gt;Do not allocate extra space for another array, you must do this by &lt;strong&gt;modifying the input array&lt;/strong&gt; &lt;a class="link" href="https://en.wikipedia.org/wiki/In-place_algorithm" target="_blank" rel="noopener"
&gt;** in-place**&lt;/a&gt; with O(1) extra memory.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Given nums = [1,1,1,2,2,3],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;It doesn&amp;#39;t matter what you leave beyond the returned length.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Given nums = [0,0,1,1,1,1,2,3,3],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;It doesn&amp;#39;t matter what values are set beyond the returned length.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Clarification:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Confused why the returned value is an integer but your answer is an array?&lt;/p&gt;
&lt;p&gt;Note that the input array is passed in by &lt;strong&gt;reference&lt;/strong&gt; , which means modification to the input array will be known to the caller as well.&lt;/p&gt;
&lt;p&gt;Internally you can think of this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;// nums is passed in by reference. (i.e., without making a copy)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;int len = removeDuplicates(nums);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;// any modification to nums in your function would be known by the caller.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;// using the length returned by your function, it prints the first len elements.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;for (int i = 0; i &amp;lt; len; i++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(nums[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個已排序的陣列nums，將其重復超過2次的部分捨棄掉，&lt;br&gt;
且使用in-place的方式來操作(在原陣列操作)，回傳最終結果的長度。&lt;/p&gt;
&lt;p&gt;這題算是之前的&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-10-linked-list-2-8384845e8ad6" target="_blank" rel="noopener"
&gt;0083. Remove Duplicates from Sorted List (Easy)&lt;/a&gt;的延伸，說真的我認為這題不該當作Medium難度XD&lt;/p&gt;
&lt;p&gt;再次提醒，當題目要求使用in-place的時候，&lt;br&gt;
對一些語言的確是可以真的用&lt;strong&gt;刪掉單點&lt;/strong&gt; 的方式來處理(例如Python)，&lt;br&gt;
但刪除這件事情也是較耗時的操作，所以沒特別要求的話，&lt;br&gt;
請依照題目希望你的方向來撰寫(&lt;strong&gt;面試則依照面試官的限制條件&lt;/strong&gt; )。&lt;/p&gt;
&lt;p&gt;我們先來講筆者直觀想到的解法，再來提leetcode上另一位高手的解。&lt;/p&gt;
&lt;p&gt;直觀而言，要怎麼能夠知道有沒有碰到&lt;strong&gt;3個&lt;/strong&gt; 以上的重復呢？&lt;br&gt;
最直接的方式就是使用一個cnt變數來記錄。&lt;br&gt;
同時，為了要確認是否是重複的數，&lt;br&gt;
我們需要記錄上一次開始重復的數last。&lt;/p&gt;
&lt;p&gt;那麼步驟就會像這樣：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果&lt;strong&gt;nums長度 ≤ 2&lt;/strong&gt; 的話，表示完全不用更動，&lt;br&gt;
直接&lt;strong&gt;回傳nums的長度&lt;/strong&gt; 即可。&lt;/li&gt;
&lt;li&gt;將&lt;strong&gt;last設為nums[0], cnt設為1,&lt;/strong&gt; 預計要覆蓋的** index j設為1。**&lt;/li&gt;
&lt;li&gt;令i從1開始一個迴圈來遍歷整個nums:&lt;br&gt;
3-a. 如果&lt;strong&gt;nums[i]不等於last&lt;/strong&gt; 的話，表示&lt;strong&gt;數字不同&lt;/strong&gt; ，&lt;br&gt;
必須將其&lt;strong&gt;覆蓋到j的位置&lt;/strong&gt; 。&lt;br&gt;
同時，我們必須更新&lt;strong&gt;last為nums[i]，j要遞增，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;cnt要重設為1&lt;/strong&gt; (用來做下一次比較)。&lt;br&gt;
3-b. 否則，如果&lt;strong&gt;兩者相等且cnt小於2&lt;/strong&gt; ，&lt;br&gt;
代表重複未超過2次，&lt;strong&gt;同樣要進行複寫和遞增j，但cnt要遞增&lt;/strong&gt; 。&lt;/li&gt;
&lt;li&gt;當整個迴圈完畢以後，&lt;strong&gt;j&lt;/strong&gt; 應該是位在&lt;strong&gt;處理過後的陣列的尾端+1&lt;/strong&gt; 的位置。&lt;br&gt;
所以&lt;strong&gt;回傳j即可代表新的陣列的總長&lt;/strong&gt; 。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;聽起來有點多，但其實寫起來並不困難，&lt;br&gt;
但還有更厲害的解法XD&lt;/p&gt;
&lt;p&gt;這邊提供了LeetCode上&lt;strong&gt;StefanPochmann&lt;/strong&gt; 的解，&lt;br&gt;
簡單來說呢，我們可以換個思路：&lt;br&gt;
由於&lt;strong&gt;整個陣列是排序過的&lt;/strong&gt; ，當我們遍歷陣列時，&lt;br&gt;
&lt;strong&gt;某個數字應不應該要覆蓋到index上&lt;/strong&gt; ，&lt;br&gt;
(筆者之前的解法將這個index叫做j，相當於這個解裡的i)&lt;br&gt;
取決於&lt;strong&gt;前面兩個數字是否跟它一樣&lt;/strong&gt; ；&lt;br&gt;
都一樣的話，就產生了&lt;strong&gt;三個相同的數&lt;/strong&gt; 的狀況，&lt;br&gt;
自然不需要再被取用，且由於排序的關係，&lt;br&gt;
我們&lt;strong&gt;只需要比較前面兩個數字中較前面的那個&lt;/strong&gt; 即可。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;當i小於2時，直接無條件覆蓋(&lt;/strong&gt; 因為不可能重複超過2次)；&lt;br&gt;
&lt;strong&gt;當遍歷到的値n大於num[i-2]&lt;/strong&gt; 時，代表&lt;strong&gt;數字不一樣&lt;/strong&gt; 或&lt;strong&gt;重複未超過2次&lt;/strong&gt; ，&lt;br&gt;
則應&lt;strong&gt;將其值覆蓋過去並遞增i&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;各自寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/fccdca5faf3d5e8e4aac30bb83d61733.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/9fa5e84db7919fbc222eaf5479cb23f1.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，我們需要遍歷整個陣列，且儲存用的輔助變數只有常數個)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 58 Two Pointer (2)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-58-two-pointer-2/</link><pubDate>Tue, 01 Oct 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-58-two-pointer-2/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 58 Two Pointer (2)" /&gt;&lt;p&gt;&lt;strong&gt;0075. Sort Colors (Medium)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(當然，Medium的拍手也可以多拍幾下啦XD)&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given an array with &lt;em&gt;n&lt;/em&gt; 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"
&gt;&lt;strong&gt;in-place&lt;/strong&gt; &lt;/a&gt;so that objects of the same color are adjacent, with the colors in the order red, white and blue.&lt;/p&gt;
&lt;p&gt;Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You are not supposed to use the library’s sort function for this problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [2,0,2,1,1,0]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: [0,0,1,1,2,2]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A rather straight forward solution is a two-pass algorithm using counting sort.&lt;br&gt;
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&gt;
&lt;li&gt;Could you come up with a one-pass algorithm using only constant space?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個陣列當中有n個物件，被著色成紅、白、藍，&lt;br&gt;
請將其以in-place的方式將同顏色排序至相鄰，並順序亦為紅白藍。&lt;br&gt;
這裡給定的陣列顏色紅/白/藍分別以0/1/2代表。&lt;/p&gt;
&lt;p&gt;如果有印象的話，大家可能還記得之前有一題&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-25-array-3-bca3bca74ca2?source=friends_link&amp;amp;sk=2b26f2e316bbfd7bc96ff372259e652a" target="_blank" rel="noopener"
&gt;Move Zeroes&lt;/a&gt;，&lt;br&gt;
差別在於這題是0, 1, 2，我們依舊可以用類似的概念來解題。&lt;/p&gt;
&lt;p&gt;使用3個變數來分別記錄0/1/2的個數，&lt;br&gt;
等到計完了，再依序覆寫到nums裡面，就可以得到答案，&lt;br&gt;
這麼做會需要&lt;strong&gt;掃過陣列兩次，第一次用來計數，第二次用來填入新的値。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;那麼，題目也問了：&lt;br&gt;
有沒有辦法給出一個&lt;strong&gt;one-pass&lt;/strong&gt; 的演算法來解此題呢？&lt;br&gt;
(one-pass algorithm意思是指說只掃過整個資料一次，詳見&lt;a class="link" href="https://en.wikipedia.org/wiki/One-pass_algorithm" target="_blank" rel="noopener"
&gt;wiki&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;我們可以仿照先前的&lt;strong&gt;Two Pointer&lt;/strong&gt; 的概念來思考。&lt;br&gt;
首先，1在這個陣列當中是我們較不在意的部分，&lt;br&gt;
因為它一定是排在整個陣列的中間，&lt;br&gt;
然後左邊區塊最後會是0，右邊區塊最後會是2。&lt;/p&gt;
&lt;p&gt;假設我們要排序，所要做的就是&lt;strong&gt;將0的部分都往左邊擺，&lt;br&gt;
將2的部分都往右邊擺&lt;/strong&gt;；最開始的時候，因為還沒排過，&lt;br&gt;
我們可以將下一個要擺放的位置命名為i0和i2，&lt;br&gt;
並假定應該要擺在0和n-1的位置。(陣列的最左邊和最右邊)&lt;br&gt;
接下來，依序掃描整個陣列(假設迭代的index為i)，會有以下三個情況。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;碰到1:&lt;br&gt;
因為將0和2都擺完以後1自然在中間，所以完全不用管它XD&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;碰到0:&lt;br&gt;
我們應該&lt;strong&gt;將其擺放在i0的位置&lt;/strong&gt; ，&lt;br&gt;
但原先i0所在的値不能平白消失，所以將其和i位置的値相交換。&lt;br&gt;
換完之後，&lt;strong&gt;i0&lt;/strong&gt; 因為已經填入0了，&lt;br&gt;
故&lt;strong&gt;下個要填入0的位置必須更新&lt;/strong&gt; ，所以&lt;strong&gt;將i0遞增&lt;/strong&gt; 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;碰到2:&lt;br&gt;
同理，&lt;strong&gt;將其擺在i2的位置，和i位置的値相交換，再遞減i2&lt;/strong&gt; ；&lt;br&gt;
需要注意的是由於&lt;strong&gt;i的位置換到我們不知道值的部分&lt;/strong&gt; ，&lt;br&gt;
&lt;strong&gt;(前面碰到0的時候換的應該都是1，所以沒有影響)&lt;/strong&gt;&lt;br&gt;
所以&lt;strong&gt;將i遞減，抵銷掉i在整個迴圈中每次加1的部分&lt;/strong&gt; ，&lt;br&gt;
以便迴圈的下一輪能檢查相同的位置。(&lt;strong&gt;檢查換過來的値&lt;/strong&gt; )&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這整個迴圈的結束時間點應該在&lt;strong&gt;i和i2交錯的時候&lt;/strong&gt; ，&lt;br&gt;
因為這代表後面都是2，既然後面已經相當於排完，&lt;br&gt;
就可以結束整個迴圈了！&lt;/p&gt;
&lt;p&gt;寫成程式碼如下，&lt;br&gt;
幾個需要簡單注意的地方是，&lt;br&gt;
當使用&lt;strong&gt;第一種方法&lt;/strong&gt; 的時候，&lt;br&gt;
其實可以直接開一個&lt;strong&gt;長度為3的陣列&lt;/strong&gt; 來儲存數字出現次數；&lt;br&gt;
其次，使用&lt;strong&gt;第二種方法&lt;/strong&gt; 時，Python當&lt;strong&gt;需要判定條件會改變的狀&lt;/strong&gt; 況時，&lt;br&gt;
&lt;strong&gt;請使用while迴圈&lt;/strong&gt; ，因為for in range的寫法沒辦法動態地去改變條件。&lt;br&gt;
(另外別忘記Python沒有++或 — ，請用+=和-=)&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/e3be7e43c19f078a715e2796a389025d.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/e498d8ad24ef8d39e560e096cdf4932a.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(N)/O(1)，不論哪個解法，最多就是掃描過2次的nums的長度，&lt;br&gt;
且我們基本上只會用到三個記錄各自數量的變數或三個索引值)&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;p&gt;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"
&gt;&lt;strong&gt;0148. Sort List (Medium)&lt;/strong&gt; &lt;/a&gt;2.&lt;a class="link" href="https://leetcode.com/problems/wiggle-sort-ii/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0324. Wiggle Sort II (Medium)&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item></channel></rss>