<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Binary Search on 跟著 Desolve 學程式</title><link>https://desolve.pages.dev/tags/binary-search/</link><description>Recent content in Binary Search on 跟著 Desolve 學程式</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Mon, 01 Feb 2021 00:00:00 +0800</lastBuildDate><atom:link href="https://desolve.pages.dev/tags/binary-search/index.xml" rel="self" type="application/rss+xml"/><item><title>從LeetCode學演算法 - 112 Binary Search (6) / Newton’s Method</title><link>https://desolve.pages.dev/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://desolve.pages.dev/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 112 Binary Search (6) / Newton’s Method" /&gt;&lt;p&gt;&lt;strong&gt;0367. Valid Perfect Square (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="寫在前面"&gt;寫在前面
&lt;/h2&gt;&lt;p&gt;目前&lt;strong&gt;0元挑戰賽&lt;/strong&gt; 的活動已經開始囉！&lt;br&gt;
只要&lt;strong&gt;修課後三個月內完課且成功錄取新工作並撰寫心得，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;課程就會全額退費喲！請使用下面連結看更詳細的規則說明：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;同時，還有限時更便宜的套組3490 (再便宜500呦！限額10名！)&lt;br&gt;
新年限量組合🎁 零元求職挑戰賽 Python 組｜從 LeetCode 學演算法&lt;/strong&gt;&lt;a class="link" href="https://hiskio.com/packages/ZXwe2p9yv" target="_blank" rel="noopener"
&gt;https://hiskio.com/packages/ZXwe2p9yv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;零元求職挑戰賽 Python 組｜從 LeetCode 學演算法 + 面試成功指南&lt;/strong&gt; &lt;a class="link" href="https://bit.ly/zeroclg?fbclid=IwAR0cGOc6L5R4j26i6BqncG0m1tPPPx5-Z1M0vAOzJpnwUrByX3q-gWE1Sfw" target="_blank" rel="noopener"
&gt;http://bit.ly/zeroclg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)&lt;br&gt;
在&lt;a class="link" href="https://www.facebook.com/groups/pythontw/permalink/10160354153893438/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Python Taiwan的連結第100篇的文章&lt;/strong&gt; &lt;/a&gt;底下，&lt;br&gt;
&lt;strong&gt;公開分享到你的臉書、按讚該篇文章、並留言告訴我說，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;「你最喜歡這一整個系列的哪一篇？為什麼？」或&lt;br&gt;
「除了從LeetCode學演算法系列以外，&lt;br&gt;
你還想要看到關於什麼方向的文章？」&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;超過20則留言的話&lt;/strong&gt; (有完成以上步驟的才算)，我們就抽一組&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;br&gt;
課程的免費兌換券進行贈送！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)&lt;/p&gt;
&lt;p&gt;容筆者工商一下，&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」&lt;/strong&gt; 開放預購啦！&lt;br&gt;
這次選了40道難度加深的LeetCode題目，&lt;br&gt;
同樣也會細部解說對應的技巧及須要掌握的演算法！&lt;br&gt;
同時這次購買進階篇的話，&lt;br&gt;
額外還加贈**「從Leetcode學演算法｜面試篇」** ！&lt;br&gt;
當中包含了&lt;strong&gt;面試準備須知分享&lt;/strong&gt; ，&lt;strong&gt;及訪談國內外不同經驗的工程師&lt;/strong&gt; ，&lt;br&gt;
讓你不論是&lt;strong&gt;想走前端/後端/一般軟工&lt;/strong&gt; 或者是&lt;strong&gt;想找國外的工作&lt;/strong&gt; ，&lt;br&gt;
是&lt;strong&gt;初學想轉職&lt;/strong&gt; 還是&lt;strong&gt;正在工作&lt;/strong&gt; ，都能夠從中得到收穫呦！&lt;br&gt;
有興趣的朋友可以使用下面的早鳥優惠～&lt;br&gt;
&lt;strong&gt;「從Leetcode學演算法｜進階篇」+「從Leetcode學演算法｜面試篇」&lt;/strong&gt; ：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/leetcodeadv" target="_blank" rel="noopener"
&gt;https://bit.ly/leetcodeadv&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;Given a &lt;strong&gt;positive&lt;/strong&gt; integer &lt;em&gt;num&lt;/em&gt;, write a function which returns True if &lt;em&gt;num&lt;/em&gt; is a perfect square else False.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt; ** Do not** use any built-in library function such as &lt;code&gt;sqrt&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/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: num = 16
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/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: num = 14
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="constraints"&gt;Constraints
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= num &amp;lt;= 2^31 - 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個正整數num，試檢驗num是否為完全平方數(也就是可以分解成兩個完全相等的數相乘)。&lt;br&gt;
請不要使用內建的sqrt或類似的函式。&lt;/p&gt;
&lt;p&gt;雖然被封印了平方根函數，但已經看到標題的讀者應該不難猜想到，&lt;br&gt;
我們可以運用一般的二分逼近法，&lt;br&gt;
去將目標(我們先稱之為x)的範圍縮小。&lt;br&gt;
當找到 x² 和num相等時，就表示num是完全平方數(回傳True)，&lt;br&gt;
否則一路找到兩個邊界交叉時，表示num不存在整數平方根，&lt;br&gt;
我們就可以回傳False。&lt;/p&gt;
&lt;p&gt;那麼，有沒有再更厲害一點的方法呢？&lt;br&gt;
這邊來介紹一下一個著名的方法，名為牛頓法(Newton’s Method)。&lt;br&gt;
我們在求x² = num當中的x，(下面方便起見，將num寫成n)&lt;br&gt;
其實相當於求 y = f(x) = x² - n在y = 0時的正根。&lt;br&gt;
假定r是這個根，我們先取一個任意一個比較大的值x0，&lt;br&gt;
那麼它對應到的座標應該是(x0, f(x0))。&lt;br&gt;
對於這個點做曲線的切線的話，應該可以得到切線方程式：&lt;br&gt;
&lt;strong&gt;y = f(x0) + f&amp;rsquo;(x0) (x-x0) &lt;br&gt;
也就是y = ax +b嘛! a就是在x0上的切線斜率，&lt;br&gt;
而x代入x0的話可以驗證y = f(x0)，&lt;br&gt;
所以這個方程式可以表達該切線沒錯。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我們將這個切線叫做L，&lt;br&gt;
那麼L和x軸的交點的x座標，應該就和r更近囉！&lt;br&gt;
(想像一下拋物線的斜度會越來越平，所以切線和x軸的交點，&lt;br&gt;
比起拋物線和x軸的交點來說應該會大一點)&lt;br&gt;
我們將後面和x軸的交點位置叫做&lt;strong&gt;x1&lt;/strong&gt; ，&lt;br&gt;
那麼就可以計算其&lt;strong&gt;斜率為 f(x0) / (x0-x1) = (x0²-n)/(x0-x1)&lt;/strong&gt; ，&lt;br&gt;
同時也等於&lt;strong&gt;f(x)的導數(就是對其微分)f’(x) = 2x&lt;/strong&gt; 。&lt;br&gt;
因此，2x0 = (x0²-n)/(x0-x1) -&amp;gt; 2x0(x0-x1) = x0²-n&lt;br&gt;
繼續化簡：&lt;br&gt;
-&amp;gt; 2x0²-2x0x1=x0²-n&lt;br&gt;
-&amp;gt; x0²+n = 2x0x1&lt;br&gt;
-&amp;gt; &lt;strong&gt;x1 = (x0 + n/x0) / 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001.png"
width="800"
height="734"
srcset="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001_hu_21abf510b9f24ccc.png 480w, https://desolve.pages.dev/post/learn-algorithm-from-leetcode-112-binary-search-6-newton-s-method/image-001_hu_c3978e53d3d16c5c.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="108"
data-flex-basis="261px"
&gt;&lt;/p&gt;
&lt;p&gt;每次取得一個更接近的x來逼近r的位置&lt;/p&gt;
&lt;p&gt;我們可以再用這個x1再取得在f(x)上的點，接下來再畫切線，&lt;br&gt;
重復上面的動作。&lt;br&gt;
當我們每次用前面這個算式迭代，就可以取得一個新的x，&lt;br&gt;
理論上它會更接近於r。(x1, x2, x3, …)&lt;br&gt;
由於要取的是整數，所以我們在計算的時候，&lt;br&gt;
就將所有的算式中的除法都取整數，&lt;br&gt;
這樣算出來的狀況，就會變得有機會更小。&lt;br&gt;
所以在運用到實際的計算時，&lt;br&gt;
我們可以設定一個迴圈，將x直接先定為num，&lt;br&gt;
當x² &amp;gt; num時，就持續迴圈，&lt;br&gt;
那麼在x持續縮小的狀況下，&lt;br&gt;
最終要嘛縮小到剛好得到一個正整數的平方根，&lt;br&gt;
要嘛就是x²已經小於num了，我們就不用繼續往下做啦！&lt;/p&gt;
&lt;p&gt;依此，寫成程式碼如下：&lt;/p&gt;
&lt;h3 id="java-java的部分請留意到大小問題我們應該要使用long來宣告變數"&gt;Java Java的部分，請留意到大小問題，我們應該要使用long來宣告變數。
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/22935065681018fa2120af827ebe5788.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Python部分則請不要忘記整數除法是”//”。&lt;/p&gt;
&lt;script src="https://gist.github.com/Desolve/a9273b962c9c694532f561c075e4a097.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(時間複雜度難以界定，最差應該是O(num)，(但二分法也是)&lt;br&gt;
平均應該優於O(log(num))，這可能也取決於初始值的取法；&lt;br&gt;
空間複雜度則為O(1))&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;相似及延伸：&lt;br&gt;
本題還有其他的解法可以參考以下連結&lt;/strong&gt;&lt;a class="link" href="https://leetcode.com/problems/valid-perfect-square/discuss/130010/Python-4-Methods-with-time-testing" target="_blank" rel="noopener"
&gt;https://leetcode.com/problems/valid-perfect-square/discuss/130010/Python-4-Methods-with-time-testing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;
&lt;p&gt;想看看其他題目嗎？&lt;br&gt;
歡迎從&lt;a class="link" href="https://desolve.pages.dev/post/learn-algorithm-from-leetcode-0/" &gt;&lt;strong&gt;第零篇&lt;/strong&gt; &lt;/a&gt;找你想要的！&lt;/p&gt;
&lt;p&gt;同時追蹤粉專以獲得更多新文章的通知：&lt;br&gt;
&lt;a class="link" href="https://www.facebook.com/learnwithdesolve" target="_blank" rel="noopener"
&gt;&lt;strong&gt;跟著Desolve學程式&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外，&lt;strong&gt;「從Leetcode學演算法｜基礎篇」&lt;/strong&gt; 已經回原價囉，&lt;br&gt;
先前的優惠碼會失效，但這邊仍然為讀者保留了300塊的折抵，&lt;br&gt;
雖然&lt;strong&gt;整捆一起買總體比較划算&lt;/strong&gt; (差290而已就有整組了阿XD)，&lt;br&gt;
如果你還是想先試試基礎課的話，&lt;br&gt;
&lt;strong&gt;300元折抵的連結&lt;/strong&gt; 在這邊：&lt;br&gt;
&lt;a class="link" href="https://bit.ly/1desolve" target="_blank" rel="noopener"
&gt;https://bit.ly/1desolve&lt;/a&gt;&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 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學演算法 - 57 Binary Search (4)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-57-binary-search-4/</link><pubDate>Sun, 29 Sep 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-57-binary-search-4/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 57 Binary Search (4)" /&gt;&lt;p&gt;&lt;strong&gt;0074. Search a 2D Matrix (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;Write an efficient algorithm that searches for a value in an &lt;em&gt;m&lt;/em&gt; x &lt;em&gt;n&lt;/em&gt; matrix. This matrix has the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integers in each row are sorted from left to right.&lt;/li&gt;
&lt;li&gt;The first integer of each row is greater than the last integer of the previous row.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix = [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1, 3, 5, 7],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [10, 11, 16, 20],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [23, 30, 34, 50]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target = 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix = [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1, 3, 5, 7],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [10, 11, 16, 20],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [23, 30, 34, 50]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target = 13
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: false
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個m x n的矩陣，此矩陣每列(row)都是從左到右升冪排序；&lt;br&gt;
同時此矩陣每列的第一個值都比前一個列的最後一個值還要大。&lt;br&gt;
試找出一個有效率的演算法，&lt;br&gt;
來處理在這個矩陣搜尋一個值是否在這裡面。&lt;/p&gt;
&lt;p&gt;有沒有覺得很熟悉？&lt;br&gt;
其實這題的延伸題目就是上一題，作為同樣Medium難度的題目，&lt;br&gt;
這題就要來得簡單許多。&lt;br&gt;
為什麼呢？&lt;br&gt;
因為按照題目的定義的話，&lt;br&gt;
我們假設從每一列的尾巴接到下一列的頭，&lt;br&gt;
最終就會得到一個完整的已排序陣列。&lt;br&gt;
那麼，已排序陣列的搜尋方式，&lt;br&gt;
我們以前已提到過了，就使用基本的&lt;strong&gt;二元搜尋法(Binary Search)&lt;/strong&gt; 即可。&lt;br&gt;
(還沒弄清楚或還不知道二元搜尋法的讀者，可以&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
&gt;&lt;strong&gt;參見前面這篇&lt;/strong&gt; &lt;/a&gt;。)&lt;/p&gt;
&lt;p&gt;那麼我們所要做的，就只剩下&lt;strong&gt;將matrix上的index，&lt;br&gt;
轉為如果攤平以後對應到的陣列index即可。&lt;/strong&gt;&lt;br&gt;
對於matrix[i][j]來說，&lt;br&gt;
由於有&lt;strong&gt;m列n行，i代表從0到i(總共i+1個列)&lt;/strong&gt; ，&lt;br&gt;
所以前面會經過i列，共 &lt;strong&gt;(i * n)&lt;/strong&gt; 個數字；&lt;br&gt;
接著要往右邊移動，&lt;br&gt;
&lt;strong&gt;j代表從0到j有j+1個數字&lt;/strong&gt; ，再相加起來，&lt;br&gt;
所以&lt;strong&gt;matrix[i][j]是整個攤平以後的第(i * n + j + 1)個數字，&lt;br&gt;
從0開始起算的話就是(i * n + j)。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因此，如果我們找到某一個中間&lt;strong&gt;index mid&lt;/strong&gt; ，&lt;br&gt;
要轉換成&lt;strong&gt;i, j&lt;/strong&gt; 的型式的話，&lt;br&gt;
就只需要分別取&lt;strong&gt;除以n得到的商和餘數&lt;/strong&gt; 即可。&lt;/p&gt;
&lt;p&gt;依此進行二元搜尋的時候，其方式就和一般的二元搜尋一模一樣，&lt;br&gt;
&lt;strong&gt;若跳出迴圈則代表該目標值不存在於matrix中，則回傳false&lt;/strong&gt; 。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/1caf4d46d0c548cea3bd1747a7fed7c8.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分請不要忘記取整數除法要用雙斜線&amp;quot;//&amp;quot;。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/2e7c615280a7f64e4ba56d1d3948d8a3.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(log(mn))/O(1))&lt;/p&gt;
&lt;h2 id="相似及延伸"&gt;相似及延伸
&lt;/h2&gt;&lt;ol&gt;
&lt;li&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-56-binary-search-3-bd76049f8765?sk=9839faa7bfcc119a10b7fbbe6f40a6df" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0240. Search a 2D Matrix II (Medium)&lt;/strong&gt; &lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 56 Binary Search (3)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-56-binary-search-3/</link><pubDate>Thu, 26 Sep 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-56-binary-search-3/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 56 Binary Search (3)" /&gt;&lt;p&gt;&lt;strong&gt;0240. Search a 2D Matrix II (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;Write an efficient algorithm that searches for a value in an &lt;em&gt;m&lt;/em&gt; x &lt;em&gt;n&lt;/em&gt; matrix. This matrix has the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integers in each row are sorted in ascending from left to right.&lt;/li&gt;
&lt;li&gt;Integers in each column are sorted in ascending from top to bottom.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Consider the following matrix:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [1, 4, 7, 11, 15],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [2, 5, 8, 12, 19],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [3, 6, 9, 16, 22],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [10, 13, 14, 17, 24],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [18, 21, 23, 26, 30]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Given target = &lt;code&gt;5&lt;/code&gt;, return &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Given target = &lt;code&gt;20&lt;/code&gt;, return &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個m x n的矩陣，此矩陣每列(row)都是從左到右升冪排序；&lt;br&gt;
同時此矩陣每行(column)都是由上到下升冪排序。&lt;br&gt;
試找出一個有效率的演算法，&lt;br&gt;
來處理在這個矩陣搜尋一個值是否在這裡面。&lt;/p&gt;
&lt;p&gt;這題乍看之下沒有這麼直觀，如果我們從matrix[0][0]出發的話，&lt;br&gt;
顯然馬上就會碰到問題：&lt;br&gt;
&lt;strong&gt;「好現在target比1大，我該往哪邊走？」&lt;/strong&gt; 看來怎麼走都不對是吧？如果透過暴力的方式來一排一排找，&lt;br&gt;
結果時間複雜度會是&lt;strong&gt;O(mn)&lt;/strong&gt; 。&lt;br&gt;
就算有想到&lt;a class="link" href="https://medium.com/@desolution/%E5%BE%9Eleetcode%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
&gt;&lt;strong&gt;Binary Search&lt;/strong&gt; &lt;/a&gt;可以處理已排序的陣列，&lt;br&gt;
每次取一行或一列來搜尋值，&lt;br&gt;
時間複雜度也只會降到&lt;strong&gt;O(m log n)或O(n log m)&lt;/strong&gt; ，&lt;br&gt;
似乎還是不那麼理想。&lt;/p&gt;
&lt;p&gt;那麼，該怎麼考慮這個題目呢？&lt;br&gt;
翻了翻提示，居然也是寫Binary Search；&lt;br&gt;
而Binary Search的精髓，&lt;br&gt;
其實就在於可以&lt;strong&gt;在每次的抉擇中保留需要的那部分的選項&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;那麼，回頭看看上面的矩陣，想要能夠靠選擇每次去掉選項，&lt;br&gt;
我們考慮看看15這個點如何？&lt;/p&gt;
&lt;p&gt;當&lt;strong&gt;target等於15&lt;/strong&gt; 的時候，就&lt;strong&gt;直接是答案了，回傳true&lt;/strong&gt; 。&lt;br&gt;
當&lt;strong&gt;target不是15&lt;/strong&gt; 的時候，可以分成&lt;strong&gt;比15大，或比15小&lt;/strong&gt; 。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;比15大&lt;/strong&gt; 的狀況：&lt;br&gt;
代表原先15的&lt;strong&gt;一整列(1, 4, 7, 11, 15)已經都不用考慮了&lt;/strong&gt; ，&lt;br&gt;
因為&lt;strong&gt;15已經是這整列的最大值&lt;/strong&gt; ，故我們可以挑到19，&lt;br&gt;
因為19這行還沒看過，&lt;br&gt;
同時(15, 19, 22, 24, 30)這當中也是越來越大，&lt;br&gt;
所以挑選19可以繼續進行比較，&lt;br&gt;
這個操作就相當於&lt;strong&gt;扣掉一整列的備選&lt;/strong&gt; 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;比15小&lt;/strong&gt; 的狀況：&lt;br&gt;
代表原先15的&lt;strong&gt;一整行(15, 19, 22, 24, 30)不用考慮了，&lt;/strong&gt;&lt;br&gt;
理由跟1.講得相似，只是這次我們就變成&lt;strong&gt;往右走挑到11&lt;/strong&gt; ，&lt;br&gt;
整個操作相當於&lt;strong&gt;扣掉一整行的備選&lt;/strong&gt; 。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我們每次刪去一行或一列，那麼總共有m列n行的話，&lt;br&gt;
最多就要操作&lt;strong&gt;m+n次&lt;/strong&gt; 才能確認target是否在matrix中。&lt;br&gt;
(因為每次扣掉一行或一列的備選嘛)&lt;/p&gt;
&lt;p&gt;所以其實再仔細一看，&lt;br&gt;
如果我們將這個矩陣往逆時針轉45度，&lt;br&gt;
(或將你的頭順時針轉45度)，&lt;br&gt;
你會發現這整個矩陣其實可以當作一個&lt;strong&gt;以15為根結點的二元樹&lt;/strong&gt; 。&lt;br&gt;
(不過由於它的特性，可以想像它還有其它不只二元樹的連結)&lt;br&gt;
(或者更準確的說，它就是&lt;strong&gt;有向圖(Oriented Graph)&lt;/strong&gt; )&lt;/p&gt;
&lt;p&gt;所以我們的整個演算法如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;檢查matrix是否正常，不正常則直接回傳false&lt;/li&gt;
&lt;li&gt;將初始點定在**(i, j)=(0, n-1)** 的位置&lt;/li&gt;
&lt;li&gt;當&lt;strong&gt;i和j都沒有超過邊界&lt;/strong&gt; 的時候，進行下面的迴圈：&lt;br&gt;
3-a. 若target和當前點的値&lt;strong&gt;相等&lt;/strong&gt; ，&lt;strong&gt;回傳true&lt;/strong&gt;&lt;br&gt;
3-b. 否則&lt;strong&gt;若target較大，將i遞增&lt;/strong&gt;&lt;br&gt;
3-c. 否則&lt;strong&gt;將j遞減&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;若迴圈結束尚未回傳，代表這個值不在矩陣內，&lt;br&gt;
回傳false結束。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;寫成程式碼如下所附。&lt;br&gt;
(也有人判斷第一步的時候用&amp;lt; 1而非==0，但測試目前沒有明顯差異，&lt;br&gt;
讀者依自己喜好選擇寫法即可。)&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/7c776ac9c439719db58ae588a14d0e6a.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/8d2f7e0afa79f5065e7fe925d98ad5c1.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(m+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;
Python Taiwan 王彥珽&lt;/strong&gt;：** 直行橫列**才對(註：中國才是橫行直列XD)&lt;br&gt;
(但我工作就會講row跟column啦)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&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;如果你／妳覺得這篇文章不錯，請給我5個拍手，並且給我5個Like。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(點開最上面的SHOW EMBED!)
&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;</description></item><item><title>從LeetCode學演算法 - 53 Binary Search (2)</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-53-binary-search-2/</link><pubDate>Sat, 21 Sep 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-53-binary-search-2/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 53 Binary Search (2)" /&gt;&lt;p&gt;&lt;strong&gt;0278. First Bad Version (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;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&gt;
&lt;p&gt;Suppose you have &lt;code&gt;n&lt;/code&gt; versions &lt;code&gt;[1, 2, ..., n]&lt;/code&gt; and you want to find out the first bad one, which causes all the following ones to be bad.&lt;/p&gt;
&lt;p&gt;You are given an API &lt;code&gt;bool isBadVersion(version)&lt;/code&gt; which will return whether &lt;code&gt;version&lt;/code&gt; is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Given n = 5, and version = 4 is the first bad version.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;call isBadVersion(3) -&amp;gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;call isBadVersion(5) -&amp;gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;call isBadVersion(4) -&amp;gt; true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;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;Then 4 is the first bad version.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;一個正在由你主導的團隊所開發的產品在最新的版本沒過品質檢驗。&lt;br&gt;
由於每個版本都是由前面的版本進版，所以當某個版本壞掉了，&lt;br&gt;
其後的版本也都會是壞的。&lt;br&gt;
假定有n個版本，你要找出第一個開始壞掉的版本。&lt;/p&gt;
&lt;p&gt;這題其實蠻真實的，&lt;br&gt;
除了一般來說不會有什麼API，&lt;br&gt;
可以看這個版本是不是壞掉這種東西(都嘛要自己測XD)&lt;br&gt;
而實際碰到這種狀況的時候，&lt;br&gt;
通常做的也是先想辦法倒回到某個版本時間點。&lt;br&gt;
這時候Project Owner就會叫大家先不要commit了，&lt;br&gt;
開始從上一個好的版本到這個版本中列出所有commits，&lt;br&gt;
再來&lt;strong&gt;切一半&lt;/strong&gt; 的位置來檢查&lt;strong&gt;中間的版本&lt;/strong&gt; 有沒有問題，&lt;br&gt;
&lt;strong&gt;沒有問題&lt;/strong&gt; 的話就代表這個&lt;strong&gt;中間點到尾端&lt;/strong&gt; 這區間才有問題；&lt;br&gt;
&lt;strong&gt;有問題&lt;/strong&gt; 的話就代表是&lt;strong&gt;開頭到中間點&lt;/strong&gt; 這個區間有問題。&lt;/p&gt;
&lt;p&gt;所以每次我們都可以排查掉一半的可能性並縮小範圍，&lt;br&gt;
最終就找到那個元凶的commit，視情況決定要做revert或其他動作。&lt;/p&gt;
&lt;p&gt;所以我們可以發現，這種連續性的東西，&lt;br&gt;
也可以用Binary Search的方式來解，只是要處理的條件就不同了。&lt;/p&gt;
&lt;p&gt;我們將較小的版本叫lo，較大的版本叫hi，&lt;br&gt;
一開始lo=1, hi=n，取中間的版本mid，&lt;br&gt;
&lt;strong&gt;當mid剛好是bad version時，並不代表可以回傳mid&lt;/strong&gt; ，&lt;br&gt;
應該&lt;strong&gt;將hi設定為mid&lt;/strong&gt; (也就是&lt;strong&gt;可能的範圍是1~mid&lt;/strong&gt; )。&lt;br&gt;
&lt;strong&gt;否則的話，代表1~mid都是清白的&lt;/strong&gt; ，&lt;br&gt;
我們可以將&lt;strong&gt;lo設定為mid+1&lt;/strong&gt; ，縮小範圍繼續搜尋。&lt;/p&gt;
&lt;p&gt;最終，當lo和hi交會的時候，&lt;br&gt;
代表我們找到出問題的那個版本，所以&lt;strong&gt;最後要回傳lo&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;Java的部分考慮到int要盡量避免溢位，&lt;br&gt;
一樣使用lo + (hi - lo) / 2的形式來計算。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/5c120ea7be03505b933dcc4778f7a6ec.js"&gt;&lt;/script&gt;
&lt;p&gt;Python的部分一樣請記得要整數除法。&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/6b2a95179dcefc6dd9e3013798a4a37b.js"&gt;&lt;/script&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(logN)/O(1))&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-6-binary-search-691c9a842a77" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0035. Search Insert Position&lt;/strong&gt; &lt;/a&gt;2.&lt;a class="link" href="https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/" target="_blank" rel="noopener"
&gt;&lt;strong&gt;0034. Find First and Last Position of Element in Sorted Array&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Special Thanks suggestions/corrections from viewers:&lt;br&gt;
(歡迎提供意見協助更正歐~)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item><item><title>從LeetCode學演算法 - 6 Binary Search</title><link>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-6-binary-search/</link><pubDate>Wed, 03 Jul 2019 00:00:00 +0800</pubDate><guid>https://desolve.pages.dev/post/learn-algorithm-from-leetcode-6-binary-search/</guid><description>&lt;img src="https://desolve.pages.dev/img/default-leetcode.webp" alt="Featured image of post 從LeetCode學演算法 - 6 Binary Search" /&gt;&lt;p&gt;&lt;strong&gt;0035. Search Insert Position (Easy)&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="question"&gt;Question
&lt;/h2&gt;&lt;p&gt;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&gt;
&lt;p&gt;You may assume no duplicates in the array.&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,3,5,6], 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-2"&gt;Example 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,3,5,6], 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-3"&gt;Example 3
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Input: [1,3,5,6], 7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="example-4"&gt;Example 4
&lt;/h3&gt;&lt;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: [1,3,5,6], 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Output: 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="分析解題"&gt;分析/解題
&lt;/h3&gt;&lt;p&gt;給定一個排序的陣列和目標值，假定陣列的數字不會重複。&lt;br&gt;
題目要求找到目標值在這個陣列中的位置；&lt;br&gt;
若無，則回傳如果要將其插入時，應插入的位置。&lt;/p&gt;
&lt;p&gt;這題是很典型的二元搜索法(&lt;strong&gt;Binary Search)&lt;/strong&gt; 。&lt;br&gt;
所謂的Binary Search，就是資料已處於被排序的狀態，那麼在這些資料內搜索某個特定值就不用一個一個找，我們可以用比較快的方法來搜尋。&lt;br&gt;
假設我們有一組排序過的陣列，&lt;br&gt;
搜尋的第一步就是取得中間點的那個值，我們先稱之為mid，&lt;br&gt;
那&lt;strong&gt;mid左邊的數必然小於mid，反之mid右邊的數必然大於mid&lt;/strong&gt; 。&lt;br&gt;
(按順序排的嘛XD)&lt;br&gt;
所以我們拿目標值target跟mid比較，&lt;br&gt;
如果&lt;strong&gt;target == mid&lt;/strong&gt; ，那&lt;strong&gt;mid所在的位置&lt;/strong&gt; 就是我們要的答案；&lt;br&gt;
如果&lt;strong&gt;target &amp;gt; mid&lt;/strong&gt; ，表示答案只可能在&lt;strong&gt;mid右邊到尾端之間(不含mid)&lt;/strong&gt; ；&lt;br&gt;
如果&lt;strong&gt;target &amp;lt; mid&lt;/strong&gt; ，表示答案只可能在&lt;strong&gt;mid左邊到開頭之間(不含mid)&lt;/strong&gt; 。&lt;br&gt;
如此一來，每次取得區塊的中間點的值，並和target做比較，&lt;br&gt;
則&lt;strong&gt;每次都可以至少刪掉一半的可能的數量&lt;/strong&gt; ，&lt;br&gt;
直到&lt;strong&gt;找到答案(target == mid)&lt;/strong&gt; ，&lt;br&gt;
或是&lt;strong&gt;區塊上下限交錯(那就表示target不存在於陣列之中)&lt;/strong&gt; ，&lt;br&gt;
我們同樣可以將&lt;strong&gt;下限&lt;/strong&gt; 的index輸出，因為它就代表應該被插入的點。&lt;/p&gt;
&lt;p&gt;例1. nums=[1,3,5,6], target=2 &lt;br&gt;
首先取下限lo = 0, 上限up = 3(頭跟尾), 中間點mi = (lo + up) / 2 = 1 -&amp;gt;&lt;br&gt;
nums[1]為3, 3 &amp;gt; 2 -&amp;gt; 將up改為mi-1=0 -&amp;gt; mi = (0 + 0) / 2 = 0 -&amp;gt;&lt;br&gt;
nums[0]為1, 1 &amp;lt; 2 -&amp;gt; 將lo改為mi+1=1 -&amp;gt; &lt;br&gt;
lo和up已交叉，故結果應輸出1。&lt;/p&gt;
&lt;p&gt;中間的值的變化如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;/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;lo up mi nums[mi]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 3 1 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 0 0 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1 0 0 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;例2. nums=[1,3,5,6], target=5&lt;br&gt;
首先取下限lo = 0, 上限up = 3(頭跟尾), 中間點mi = (lo + up) / 2 = 1 -&amp;gt;&lt;br&gt;
nums[1]為3, 3 &amp;lt; 5 -&amp;gt; 將lo改為mi+1=2 -&amp;gt;mi = (2+3)/2 = 2 -&amp;gt;&lt;br&gt;
nums[2]為5, 5==5 -&amp;gt; 直接輸出mi的值2即是答案。&lt;/p&gt;
&lt;p&gt;中間的值的變化如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;/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;lo up mi nums[mi]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 3 1 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2 3 2 5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面也列出[1,3,5,6], 7跟[1,3,5,6], 0的值變化的過程，&lt;br&gt;
有興趣或對整個邏輯還沒有弄得很明白的讀者可以嘗試推導一遍。&lt;/p&gt;
&lt;p&gt;nums=[1,3,5,6], target=7 -&amp;gt; ans = 4&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lo up mi nums[mi]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 3 1 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2 3 2 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3 3 3 6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4 3 3 6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;nums=[1,3,5,6], target=0 -&amp;gt; ans = 0&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#8087a2"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lo up mi nums[mi]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 3 1 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 0 0 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;0 -1 -1 6 #(這個是用python輸出的，所以nums[-1] == 6)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;底下的解法看個人喜好命名均可。&lt;/p&gt;
&lt;h3 id="java"&gt;Java
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/1e8ce8f5cb9f93d7735cddc4acd5fad0.js"&gt;&lt;/script&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;script src="https://gist.github.com/Desolve/97cea741906acfed250c644a263524df.js"&gt;&lt;/script&gt;
&lt;p&gt;在這個解題過程，由於每次我們都會將範圍縮小一半，&lt;br&gt;
所以總共比對的次數就相當於求這個陣列的長度是2的幾次方，&lt;br&gt;
故時間複雜度為&lt;strong&gt;O(logN)&lt;/strong&gt; 。&lt;br&gt;
(電腦科學領域的對數一般不特別提的話通常是以2為底)&lt;/p&gt;
&lt;p&gt;事實上，Java中也有提供 &lt;strong&gt;Arrays.binarySearch(int[] a, int key)&lt;/strong&gt; 於utils的函式庫中，但有一點不一樣的是，當找不到target的時候，&lt;br&gt;
如果插入該key所在位置為index，則回傳值為**-index-1** 。&lt;br&gt;
取負號是為了和key存在於陣列的狀況做分隔，&lt;br&gt;
額外減1則是為了將&lt;strong&gt;key在0的位置&lt;/strong&gt; 及&lt;strong&gt;key應該要插入在0的位置&lt;/strong&gt; 做區分。&lt;br&gt;
(因為0取負號還是0)&lt;/p&gt;
&lt;p&gt;Binary Search是在排序陣列或一些有序的資料結構中很常用到的演算法，&lt;br&gt;
以後在談到&lt;strong&gt;二元搜尋樹(BST, Binary Search Tree)&lt;/strong&gt; 的時候也會用到它。&lt;br&gt;
所以如何寫一個二元搜尋的簡單方法是很有用的，可以的話務請熟練XD&lt;/p&gt;
&lt;h2 id="面試實際可能會遇到的問題"&gt;面試實際可能會遇到的問題
&lt;/h2&gt;&lt;p&gt;「(Java)如果上限接近Integer.MAX_VALUE的話相加有overflow的可能？」&lt;br&gt;
(將(lo+up)/2改成lo + (up-lo)/2，可以保證不會溢出)&lt;/p&gt;
&lt;p&gt;「時間/空間複雜度？」&lt;br&gt;
(O(logN), O(1))&lt;/p&gt;
&lt;p&gt;「我想知道到底結果target是否存在array中，但不想額外加回傳的值？」&lt;br&gt;
(如上面提到的，將&lt;strong&gt;插入&lt;/strong&gt; 的狀況改為**-index-1** 來表達)&lt;/p&gt;
&lt;p&gt;從LeetCode學演算法，我們下次見囉，掰~&lt;/p&gt;</description></item></channel></rss>