<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://emre.me/feed.xml" rel="self" type="application/atom+xml" /><link href="https://emre.me/" rel="alternate" type="text/html" /><updated>2024-07-09T17:31:08+03:00</updated><id>https://emre.me/feed.xml</id><title type="html">emre.me</title><subtitle>Adventures in Software Engineering</subtitle><author><name>Emre Bolat</name><email>emre@emre.me</email></author><entry><title type="html">Tarjan’s Algorithm: Strongly Connected Components</title><link href="https://emre.me/algorithms/tarjans-algorithm/" rel="alternate" type="text/html" title="Tarjan’s Algorithm: Strongly Connected Components" /><published>2020-03-07T00:00:00+03:00</published><updated>2020-03-07T00:00:00+03:00</updated><id>https://emre.me/algorithms/tarjans-algorithm</id><content type="html" xml:base="https://emre.me/algorithms/tarjans-algorithm/"><![CDATA[<p><strong>Tarjan’s algorithm</strong><a href="#references"><sup>1</sup></a><sup>, </sup><a href="#references"><sup>2</sup></a> which runs in <em>linear time</em> is an algorithm in <a href="https://emre.me/data-structures/graphs/">Graph Theory</a> for finding the <strong>strongly connected components</strong> of a <a href="https://emre.me/data-structures/graphs/#directed-or-undirected">directed graph</a>.</p>

<h2 id="bridges-and-articulation-points">Bridges and Articulation Points</h2>

<p><strong>Bridges</strong> and <strong>Articulation Points</strong> are important in <a href="https://emre.me/data-structures/graphs/">Graph Theory</a> because in real-world situations, they often hint <em>weak points</em>, <em>bottlenecks</em> or <em>vulnerabilities</em> in the graph. Therefore, it is important to be able to quickly <em>find</em> and <em>detect</em> <strong>where</strong> and <strong>when</strong> they occur.</p>

<h3 id="bridge">Bridge</h3>
<p>A <a href="https://en.wikipedia.org/wiki/Bridge_(graph_theory)">Bridge</a> (or <strong>cut-edge</strong>) in <a href="https://emre.me/data-structures/graphs/">graph theory</a> is any <strong>edge</strong> in a graph <em>whose removal increases the number of connected components</em>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-bridge.png" alt="Bridge in Graph Theory" /></p>

<p>Lines with the <em>red color</em> are <strong>bridges</strong> because if you remove any of them, the graph is <em>divided into two components</em>.</p>

<h3 id="articulation-point">Articulation Point</h3>
<p>An <a href="https://en.wikipedia.org/wiki/Biconnected_component">Articulation Point</a> (or <strong>cut-vertex</strong>) is any <strong>node</strong> in a graph <em>whose removal increases the number of connected components</em>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-articulation-point.png" alt="Articulation Point in Graph Theory" /></p>

<p>Nodes marked with <em>orange color</em> are <strong>articulation points</strong> because if you remove any of them, graph is <em>devided into two components</em>.</p>

<h2 id="tarjans-algorithm">Tarjan’s Algorithm</h2>
<p><a href="https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm">Tarjan’s Algorithm</a> provides a very effective way to find these <strong>bridges</strong> and <strong>articulation points</strong> in linear time. We can explain this algorithm in <strong>3</strong> steps:</p>

<h3 id="step-1">Step 1</h3>
<p>Start at <strong>any</strong> <em>node</em> and do a <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a> traversal, labeling nodes with an <em>increasing</em> <code class="language-plaintext highlighter-rouge">id</code> value as you go.</p>

<p><img src="https://cdn.emre.me/2020-03-07-dfs-traversal.gif" alt="DFS Lebeling" /></p>

<h3 id="step-2">Step 2</h3>

<p>Keep track the <code class="language-plaintext highlighter-rouge">id</code> of <em>each</em> node and the <em>smallest</em> <a href="#what-is-low-link">low link</a> value.</p>

<h4 id="what-is-low-link">What is Low Link?</h4>
<p><strong>Low Link Value</strong> of a node is defined as the smallest <code class="language-plaintext highlighter-rouge">id</code> reachable from that node when doing a <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, including itself.</p>

<p>Initially, all <a href="#what-is-low-link">low link</a> values can be initialized to the each node <code class="language-plaintext highlighter-rouge">id</code>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-low-link1.png" alt="Low Link Initial" /></p>

<p>If we inspect <em>node 1</em> and <em>node 2</em>, we will notice that <strong>there exist a path</strong> going from <em>node 1</em> and <em>node 2</em> to <em>node 0</em>.</p>

<p>So, we should update both <em>node 1</em> and <em>node 2</em> <a href="#what-is-low-link">low link</a> values to <strong>0</strong>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-low-link2.png" alt="Low Link 0-1-2" /></p>

<p>However, <em>node 3</em>, <em>node 4</em> and <em>node 5</em> are already at their optimal <a href="#what-is-low-link">low link</a> value because there are <strong>no other node</strong> they can reach with a smaller <code class="language-plaintext highlighter-rouge">id</code>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-low-link3.png" alt="Low Link 3-4-5" /></p>

<p>For <em>node 6</em>, <em>node 7</em> and <em>node 8</em>, <strong>there is a path</strong> from <em>node 6</em>, <em>node 7</em> and <em>node 8</em> to <em>node 5</em>.</p>

<p>So, we should update <em>node 6</em>, <em>node 7</em> and <em>node 8</em> <a href="#what-is-low-link">low link</a> values to <strong>5</strong>.</p>

<p><img src="https://cdn.emre.me/2020-03-07-low-link4.png" alt="Low Link 6-7-8" /></p>

<h3 id="step-3">Step 3</h3>

<p>During the <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, bridges will be found where the <code class="language-plaintext highlighter-rouge">id</code> of node your edge is coming from is <strong>less than</strong> the <a href="#what-is-low-link">low link</a> value of the node your edge is going to.</p>

<p><img src="https://cdn.emre.me/2020-03-07-is-bridge.png" alt="Is Bridge?" /></p>

<h2 id="problem-critical-connections-in-a-network">Problem: Critical Connections in a Network</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/critical-connections-in-a-network/"><strong>LeetCode 1192 - Critical Connections in a Network</strong> [<em>hard</em>]</a></p>

<p>There are <code class="language-plaintext highlighter-rouge">n</code> servers numbered from <strong>0</strong> to <strong>n-1</strong> connected by undirected server-to-server connections forming a network where <code class="language-plaintext highlighter-rouge">connections[i] = [a, b]</code> represents a connection between servers <strong>a</strong> and <strong>b</strong>. Any server can reach any other server directly or indirectly through the network.</p>

<p>A critical connection is a connection that, if removed, will make some server unable to reach some other server.</p>

<p>Return all critical connections in the network in any order.</p>

<p><strong>Example 1:</strong></p>

<p><img src="https://cdn.emre.me/2020-03-07-critical-connections.png" alt="Critical Connections" /></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">connections</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">]]</span>
<span class="n">Output</span><span class="p">:</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">]]</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="p">[[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span> <span class="ow">is</span> <span class="n">also</span> <span class="n">accepted</span><span class="p">.</span>
</code></pre></div></div>

<p><strong>Constraints:</strong></p>

<ul>
  <li>1 &lt;= <code class="language-plaintext highlighter-rouge">n</code> &lt;= 10<sup>5</sup></li>
  <li><code class="language-plaintext highlighter-rouge">n-1</code> &lt;= <code class="language-plaintext highlighter-rouge">connections.length</code> &lt;= 10<sup>5</sup></li>
  <li><code class="language-plaintext highlighter-rouge">connections[i][0] != connections[i][1]</code></li>
  <li>There are no repeated connections.</li>
</ul>


</div>

<h3 id="solution-with-using-tarjans-algorithm">Solution with using Tarjan’s Algorithm</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">criticalConnections</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">connections</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]]:</span>
        <span class="k">def</span> <span class="nf">make_graph</span><span class="p">(</span><span class="n">connections</span><span class="p">):</span>
            <span class="n">graph</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="n">connections</span><span class="p">:</span>
                <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">edge</span>
                <span class="n">graph</span><span class="p">[</span><span class="n">a</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
                <span class="n">graph</span><span class="p">[</span><span class="n">b</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">graph</span>

        <span class="n">graph</span> <span class="o">=</span> <span class="n">make_graph</span><span class="p">(</span><span class="n">connections</span><span class="p">)</span>

        <span class="nb">id</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">prev_node</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>  <span class="c1"># at first there is no prev_node. we set it to -1
</span>        <span class="n">ids</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span>  <span class="c1"># tracks ids of nodes
</span>        <span class="n">low_links</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span>  <span class="c1"># tracks low link value (default value is the index)
</span>        <span class="n">visited</span> <span class="o">=</span> <span class="p">[</span><span class="bp">False</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span>  <span class="c1"># tracks DFS visit status
</span>
        <span class="n">bridges</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">dfs</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">prev_node</span><span class="p">,</span> <span class="n">bridges</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">ids</span><span class="p">,</span> <span class="n">low_links</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">bridges</span>

    <span class="k">def</span> <span class="nf">dfs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">prev_node</span><span class="p">,</span> <span class="n">bridges</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">ids</span><span class="p">,</span> <span class="n">low_links</span><span class="p">):</span>
        <span class="n">visited</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">low_links</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="nb">id</span>
        <span class="n">ids</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="nb">id</span>
        <span class="nb">id</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="k">for</span> <span class="n">next_node</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
            <span class="k">if</span> <span class="n">next_node</span> <span class="o">==</span> <span class="n">prev_node</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">visited</span><span class="p">[</span><span class="n">next_node</span><span class="p">]:</span>
                <span class="bp">self</span><span class="p">.</span><span class="n">dfs</span><span class="p">(</span><span class="n">next_node</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">bridges</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">ids</span><span class="p">,</span> <span class="n">low_links</span><span class="p">)</span>
                <span class="n">low_links</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">low_links</span><span class="p">[</span><span class="n">node</span><span class="p">],</span> <span class="n">low_links</span><span class="p">[</span><span class="n">next_node</span><span class="p">])</span>  <span class="c1"># on callback, generates low link values
</span>                <span class="k">if</span> <span class="n">ids</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">low_links</span><span class="p">[</span><span class="n">next_node</span><span class="p">]:</span>  <span class="c1"># found the bridge!
</span>                    <span class="n">bridges</span><span class="p">.</span><span class="n">append</span><span class="p">([</span><span class="n">node</span><span class="p">,</span> <span class="n">next_node</span><span class="p">])</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># tried to visit an already visited node, which may have a lower id than the current low link value
</span>                <span class="n">low_links</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">low_links</span><span class="p">[</span><span class="n">node</span><span class="p">],</span> <span class="n">ids</span><span class="p">[</span><span class="n">next_node</span><span class="p">])</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(E + V)</strong> –&gt; One pass, linear time solution</p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong></p>

<h2 id="references">References</h2>
<ol>
  <li>Wikipedia, <em><a href="https://en.wikipedia.org/wiki/Robert_Tarjan">Robert Tarjan</a></em></li>
  <li>Wikipedia, <em><a href="https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm">Tarjan’s strongly connected components algorithm</a></em></li>
  <li>YouTube, <em><a href="https://www.youtube.com/watch?v=aZXi1unBdJA">William Fiset - Bridges and Articulation points - Graph Theory</a></em></li>
</ol>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="algorithms" /><category term="algorithms" /><category term="graphs" /><summary type="html"><![CDATA[Tarjan’s algorithm1, 2 which runs in linear time is an algorithm in Graph Theory for finding the strongly connected components of a directed graph.]]></summary></entry><entry><title type="html">Coding Patterns: Longest Common Substring/Subsequence (DP)</title><link href="https://emre.me/coding-patterns/longest-common-substring-subsequence/" rel="alternate" type="text/html" title="Coding Patterns: Longest Common Substring/Subsequence (DP)" /><published>2020-01-27T00:00:00+03:00</published><updated>2020-01-27T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/longest-common-substring-subsequence</id><content type="html" xml:base="https://emre.me/coding-patterns/longest-common-substring-subsequence/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a>, <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a>, <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a>, <a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a>, <a href="https://emre.me/coding-patterns/bitwise-xor">Bitwise XOR</a>, <a href="https://emre.me/coding-patterns/staircase">Staircase</a> and <a href="https://emre.me/coding-patterns/palindromes">Palindromes</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/longest-common-substring-subsequence">Longest Common Substring / Subsequence</a> pattern which is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <em>longest</em> / <em>shortest</em> <em>common</em> <em>strings</em>, <em>substrings</em>, <em>subsequences</em> etc.</p>

<p>If you need to refresh your knowledge of <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a>, you may want to check it before diving into more advanced problems.</p>

<h2 id="problem-longest-common-subsequence">Problem: Longest Common Subsequence</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/longest-common-subsequence/"><strong>LeetCode 1143 - Longest Common Subsequence</strong> [<em>medium</em>]</a></p>

<p>Given two strings <code class="language-plaintext highlighter-rouge">text1</code> and <code class="language-plaintext highlighter-rouge">text2</code>, return the length of their <em>longest common subsequence</em>.</p>

<p>A common subsequence of two strings is a subsequence that is common to both strings. If there is no common subsequence, return 0.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">text1</span> <span class="o">=</span> <span class="s">"abcde"</span><span class="p">,</span> <span class="n">text2</span> <span class="o">=</span> <span class="s">"ace"</span> 
<span class="n">Output</span><span class="p">:</span> <span class="mi">3</span>  
<span class="n">Explanation</span><span class="p">:</span> <span class="n">The</span> <span class="n">longest</span> <span class="n">common</span> <span class="n">subsequence</span> <span class="ow">is</span> <span class="s">"ace"</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">length</span> <span class="ow">is</span> <span class="mf">3.</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">text1</span> <span class="o">=</span> <span class="s">"abc"</span><span class="p">,</span> <span class="n">text2</span> <span class="o">=</span> <span class="s">"abc"</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">3</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">The</span> <span class="n">longest</span> <span class="n">common</span> <span class="n">subsequence</span> <span class="ow">is</span> <span class="s">"abc"</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">length</span> <span class="ow">is</span> <span class="mf">3.</span>
</code></pre></div></div>

<p><strong>Example 3:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">text1</span> <span class="o">=</span> <span class="s">"abc"</span><span class="p">,</span> <span class="n">text2</span> <span class="o">=</span> <span class="s">"def"</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">0</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">There</span> <span class="ow">is</span> <span class="n">no</span> <span class="n">such</span> <span class="n">common</span> <span class="n">subsequence</span><span class="p">,</span> <span class="n">so</span> <span class="n">the</span> <span class="n">result</span> <span class="ow">is</span> <span class="mf">0.</span>
</code></pre></div></div>

<p><strong>Constraints:</strong></p>

<ul>
  <li>1 &lt;= <code class="language-plaintext highlighter-rouge">text1.length</code> &lt;= 1000</li>
  <li>1 &lt;= <code class="language-plaintext highlighter-rouge">text2.length</code> &lt;= 1000</li>
  <li>The input strings consist of lowercase English characters only.</li>
</ul>


</div>

<h3 id="brute-force-solution">Brute Force Solution</h3>

<blockquote>
  <p>A <a href="https://en.wikipedia.org/wiki/Subsequence">subsequence</a> of a string is a <em>new</em> string generated from the <em>original</em> string with some characters (can be none) deleted without changing the relative order of the remaining characters. (eg, <em>“ace”</em> is a subsequence of <em>“abcde”</em> while <em>“aec”</em> is <strong>not</strong>).</p>
</blockquote>

<p>As a <strong>brute force</strong> solution, we can try all subsequences of <code class="language-plaintext highlighter-rouge">text1</code> and <code class="language-plaintext highlighter-rouge">text2</code> to find the longest one.</p>

<ul>
  <li>if the characters <code class="language-plaintext highlighter-rouge">text1[i]</code> matches <code class="language-plaintext highlighter-rouge">text2[j]</code>, we can recursively match the others.</li>
  <li>if the characters <code class="language-plaintext highlighter-rouge">text1[i]</code> and <code class="language-plaintext highlighter-rouge">text2[j]</code> does <strong>not</strong> match, we will make two recursive calls by skipping one character from each string.</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestCommonSubsequence</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text1</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">text2</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">text1</span><span class="p">)</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">text2</span><span class="p">):</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="n">text1</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">text2</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
            <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>

        <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">),</span>
                   <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>
<p><strong>Time Complexity</strong>: <strong>O(2<sup>N+M</sup>)</strong> where <strong>N</strong> and <strong>M</strong> are the lengths of two input strings.</p>

<p><strong>Space Complexity</strong>: <strong>O(N + M)</strong> which is used to store the recursion stack.</p>

<h3 id="top-down-dynamic-programming-with-memoization">Top-down Dynamic Programming with Memoization</h3>

<p>We can use a two-dimensional array to store the already solved subproblems.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestCommonSubsequence</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text1</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">text2</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">memo</span> <span class="o">=</span> <span class="p">[[</span><span class="o">-</span><span class="mi">1</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text2</span><span class="p">))]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text1</span><span class="p">))]</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memo</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">text1</span><span class="p">)</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">text2</span><span class="p">):</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">text1</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">text2</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">),</span>
                                 <span class="bp">self</span><span class="p">.</span><span class="n">longestCommonSubsequence_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">text1</span><span class="p">,</span> <span class="n">text2</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
</code></pre></div></div>
<p><strong>Time Complexity</strong>: <strong>O(N * M)</strong> where <strong>N</strong> and <strong>M</strong> are the lengths of two input strings.</p>

<p><strong>Space Complexity</strong>: <strong>O(N * M)</strong></p>

<h3 id="bottom-up-dynamic-programming-with-tabulation">Bottom-up Dynamic Programming with Tabulation</h3>

<p>Lets create our two dimensional array in a bottom-up fashion.</p>

<ul>
  <li>if the characters <code class="language-plaintext highlighter-rouge">text1[i]</code> matches <code class="language-plaintext highlighter-rouge">text2[j]</code>, the length of the common subsequence would be one plus the length of the common subsequence until the <code class="language-plaintext highlighter-rouge">i-1</code> and <code class="language-plaintext highlighter-rouge">j-1</code> indexes.</li>
  <li>if the characters <code class="language-plaintext highlighter-rouge">text1[i]</code> and <code class="language-plaintext highlighter-rouge">text2[j]</code> does <strong>not</strong> match, we take the longest sequence by skipping one character either from <strong>i<sup>th</sup></strong> string or <strong>j<sup>th</sup></strong> character from respective strings.</li>
</ul>

<p>Our overall algorithm is;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">text1</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">text2</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
    <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">memo</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>

<p>and the solution is;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestCommonSubsequence</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text1</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">text2</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">memo</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
        <span class="n">max_length</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">text1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">text2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">text1</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">text2</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]:</span>
                    <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">memo</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>

                <span class="n">max_length</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">max_length</span><span class="p">,</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">])</span>
        <span class="k">return</span> <span class="n">max_length</span>
</code></pre></div></div>
<p><strong>Time Complexity</strong>: <strong>O(N * M)</strong> where <strong>N</strong> and <strong>M</strong> are the lengths of two input strings.</p>

<p><strong>Space Complexity</strong>: <strong>O(N * M)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>

<p><a href="https://emre.me/coding-patterns/longest-common-substring-subsequence">Longest Common Substring / Subsequence</a> pattern is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <em>longest</em> / <em>shortest</em> <em>common</em> <em>strings</em>, <em>substrings</em>, <em>subsequences</em> etc.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/edit-distance/">LeetCode 72 - Edit Distance [<em>hard</em>]</a></li>
  <li><a href="https://leetcode.com/problems/interleaving-string/">LeetCode 97 - Interleaving String [<em>hard</em>]</a></li>
  <li><a href="https://leetcode.com/problems/longest-increasing-subsequence/">LeetCode 300 - Longest Increasing Subsequence [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/shortest-common-supersequence/">LeetCode 1092 - Shortest Common Supersequence [<em>hard</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><category term="dynamic-programming" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Palindromes (DP)</title><link href="https://emre.me/coding-patterns/palindromes/" rel="alternate" type="text/html" title="Coding Patterns: Palindromes (DP)" /><published>2020-01-22T00:00:00+03:00</published><updated>2020-01-22T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/palindromes</id><content type="html" xml:base="https://emre.me/coding-patterns/palindromes/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a>, <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a>, <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a>, <a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a>, <a href="https://emre.me/coding-patterns/bitwise-xor">Bitwise XOR</a> and <a href="https://emre.me/coding-patterns/staircase">Staircase</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/palindromes">Palindromes</a> pattern which is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <strong>palindromes</strong> and <strong>palindromic</strong> <em>strings</em>, <em>substrings</em>, <em>subsequences</em> etc.</p>

<p>If you need to refresh your knowledge of <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a>, you may want to check it before diving into more advanced problems.</p>

<h2 id="problem-longest-palindromic-subsequence">Problem: Longest Palindromic Subsequence</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/longest-palindromic-subsequence/"><strong>LeetCode 516 - Longest Palindromic Subsequence</strong> [<em>medium</em>]</a></p>

<p>Given a string <strong>s</strong>, find the longest <a href="https://en.wikipedia.org/wiki/Palindrome">palindromic</a> subsequence’s length in <strong>s</strong>. You may assume that the <em>maximum length</em> of <strong>s</strong> is <strong>1000</strong>.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="s">"bbbab"</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">4</span>
<span class="n">One</span> <span class="n">possible</span> <span class="n">longest</span> <span class="n">palindromic</span> <span class="n">subsequence</span> <span class="ow">is</span> <span class="s">"bbbb"</span><span class="p">.</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="s">"cbbd"</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">2</span>
<span class="n">One</span> <span class="n">possible</span> <span class="n">longest</span> <span class="n">palindromic</span> <span class="n">subsequence</span> <span class="ow">is</span> <span class="s">"bb"</span><span class="p">.</span>
</code></pre></div></div>


</div>

<h3 id="brute-force-solution">Brute Force Solution</h3>

<blockquote>
  <p>A <strong>palindrome</strong> is a <em>word</em>, <em>number</em>, <em>phrase</em>, or other sequence of characters which <strong>reads the same backward as forward</strong>, such as <em>madam</em>, <em>racecar</em>, or the number <em>10801</em>.</p>

  <p>Sentence-length palindromes may be written when allowances are made for adjustments to capital letters, punctuation, and word dividers, such as “<em>A man, a plan, a canal, Panama!</em>”, “<em>Was it a car or a cat I saw?</em>” etc.<a href="#references"><sup>1</sup></a></p>
</blockquote>

<p>As a <strong>brute force</strong> solution, we can try all <em>subsequences</em> of the given <em>sequence</em>. Starting from the beginning and the end of the sequence;</p>
<ul>
  <li>if the elements at the beginning and the end are the same, we can increment the counter by <strong>2</strong> and make a recursive call to remaining subsequences</li>
  <li>we will skip one element either from the beginning or from the end o make two recursive calls for the remaining subsequence</li>
</ul>

<p>If the <strong>first option</strong> applies then it will give us the length of <em>Longest Palindromic Substring (<strong>LPS</strong>)</em>.</p>

<p>Otherwise, the length of <em>Longest Palindromic Substring (<strong>LPS</strong>)</em> will be the maximum number returned by the <em>two</em> recursive calls from <strong>the second option</strong>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestPalindromeSubseq</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">start</span> <span class="o">&gt;</span> <span class="n">end</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>

        <span class="c1"># every sequence with one element is a palindrome of length 1
</span>        <span class="k">if</span> <span class="n">start</span> <span class="o">==</span> <span class="n">end</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>

        <span class="c1"># case 1: elements at the beginning and the end are the same
</span>        <span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">]:</span>
            <span class="k">return</span> <span class="mi">2</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

        <span class="c1"># case 2: skip one element either from the beginning or the end
</span>        <span class="n">subseq1</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span><span class="p">)</span>
        <span class="n">subseq2</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

        <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">subseq1</span><span class="p">,</span> <span class="n">subseq2</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(2<sup>N</sup>)</strong> because we are making <strong>2</strong> recursive calls in the same function.</p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong> which is used to store the recursion stack.</p>

<h3 id="top-down-dynamic-programming-with-memoization">Top-down Dynamic Programming with Memoization</h3>

<p><code class="language-plaintext highlighter-rouge">start</code> and <code class="language-plaintext highlighter-rouge">end</code> are two changing values of our recursive function in the <a href="#brute-force-solution">Brute Force Solution</a>. So, we can store the results of all subsequences in a two-dimensional array to <em>memoize</em> them.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestPalindromeSubseq</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">memo</span> <span class="o">=</span> <span class="p">[[</span><span class="o">-</span><span class="mi">1</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">))]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">))]</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memo</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">start</span> <span class="o">&gt;</span> <span class="n">end</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>

        <span class="c1"># every sequence with one element is a palindrome of length 1
</span>        <span class="k">if</span> <span class="n">start</span> <span class="o">==</span> <span class="n">end</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
            <span class="c1"># case 1: elements at the beginning and the end are the same
</span>            <span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">]:</span>
                <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># case 2: skip one element either from the beginning or the end
</span>                <span class="n">subseq1</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span><span class="p">)</span>
                <span class="n">subseq2</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">longestPalindromeSubseq_recursive</span><span class="p">(</span><span class="n">memo</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
                <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">subseq1</span><span class="p">,</span> <span class="n">subseq2</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N<sup>2</sup>)</strong> because <a href="https://emre.me/algorithms/dynamic-programming/#memoization">memoization</a> array, <code class="language-plaintext highlighter-rouge">memo[len(s)][len(s)]</code>. We will not have more than <strong>N*N</strong> subsequences.</p>

<p><strong>Space Complexity</strong>: <strong>O(N<sup>2</sup> + N)</strong> == <strong>O(N<sup>2</sup>)</strong> because we used <strong>N<sup>2</sup></strong> for <a href="https://emre.me/algorithms/dynamic-programming/#memoization">memoization</a> array and <strong>N</strong> for recursive stack.</p>

<h3 id="bottom-up-dynamic-programming-with-tabulation">Bottom-up Dynamic Programming with Tabulation</h3>

<p>We can build our two-dimensional <a href="https://emre.me/algorithms/dynamic-programming/#memoization">memoization</a> array in a bottom-up fashion, adding one element at a time.</p>

<ul>
  <li>if the element at the <code class="language-plaintext highlighter-rouge">start</code> and the <code class="language-plaintext highlighter-rouge">end</code> is matching, the length of <em>Longest Palindromic Substring (<strong>LPS</strong>)</em> is 2 plus the length of <strong>LPS</strong> till <code class="language-plaintext highlighter-rouge">start+1</code> and <code class="language-plaintext highlighter-rouge">end-1</code>.</li>
  <li>if the element at the <code class="language-plaintext highlighter-rouge">start</code> does <strong>not</strong> match the element at the <code class="language-plaintext highlighter-rouge">end</code>, we will take the <code class="language-plaintext highlighter-rouge">max</code> of <strong>LPS</strong> by either skipping the element at <code class="language-plaintext highlighter-rouge">start</code> or <code class="language-plaintext highlighter-rouge">end</code></li>
</ul>

<p>So the overall algorith will be;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">]:</span>
    <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">memo</span><span class="p">[</span><span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">end</span><span class="p">],</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>

<p>and the solution;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">longestPalindromeSubseq</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">memo</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">))]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">))]</span>

        <span class="c1"># every sequence with one element is a palindrome of length 1
</span>        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)):</span>
            <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

        <span class="k">for</span> <span class="n">start</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
            <span class="k">for</span> <span class="n">end</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)):</span>
                <span class="c1"># case 1: elements at the beginning and the end are the same
</span>                <span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">]:</span>
                    <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
                <span class="k">else</span><span class="p">:</span>  <span class="c1"># case 2: skip one element either from the beginning or the end
</span>                    <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">memo</span><span class="p">[</span><span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">end</span><span class="p">],</span> <span class="n">memo</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>

        <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N<sup>2</sup>)</strong></p>

<p><strong>Space Complexity</strong>: <strong>O(N<sup>2</sup>)</strong> where <strong>N</strong> is the input sequence.</p>

<h2 id="how-to-identify">How to identify?</h2>

<p><a href="https://emre.me/coding-patterns/palindromes">Palindromes</a> pattern is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <strong>palindromes</strong> and <strong>palindromic</strong> <em>strings</em>, <em>substrings</em>, <em>subsequences</em> etc.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/longest-palindromic-substring/">LeetCode 5 - Longest Palindromic Substring [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/palindrome-partitioning/">LeetCode 131 - Palindrome Partitioning [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/palindromic-substrings/">LeetCode 647 - Palindromic Substrings [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/valid-palindrome-iii/">LeetCode 1216 - Valid Palindrome III [<em>hard</em>] [<em>premium</em>]</a></li>
</ul>

<h2 id="references">References</h2>
<ol>
  <li>Wikipedia, <em><a href="https://en.wikipedia.org/wiki/Palindrome">Palindrome</a></em></li>
</ol>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><category term="dynamic-programming" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Staircase (DP)</title><link href="https://emre.me/coding-patterns/staircase/" rel="alternate" type="text/html" title="Coding Patterns: Staircase (DP)" /><published>2020-01-19T00:00:00+03:00</published><updated>2020-01-19T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/staircase</id><content type="html" xml:base="https://emre.me/coding-patterns/staircase/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a>, <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a>, <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a>, <a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a> and <a href="https://emre.me/coding-patterns/bitwise-xor">Bitwise XOR</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/staircase">Staircase</a> pattern which is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <em>minimum/maximum steps</em>, <em>jumps</em>, <em>stairs</em>, <em>fibonacci numbers</em> etc. to reach a target.</p>

<p>If you need to refresh your knowledge of <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a>, you may want to check the <a href="https://emre.me/algorithms/dynamic-programming/#memoization">Fibonacci Number Problem</a> before diving into more advanced problems.</p>

<h2 id="problem-climbing-stairs">Problem: Climbing Stairs</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/climbing-stairs/"><strong>LeetCode 70 - Climbing Stairs</strong> [<em>easy</em>]</a></p>

<p>You are climbing a stair case. It takes <strong>n</strong> steps to reach to the top.
Each time you can either climb <strong>1</strong> or <strong>2</strong> steps. In how many <em>distinct</em> ways can you climb to the top?</p>

<p><strong>Note:</strong></p>

<p>Given n will be a positive integer.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="mi">2</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">2</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">There</span> <span class="n">are</span> <span class="n">two</span> <span class="n">ways</span> <span class="n">to</span> <span class="n">climb</span> <span class="n">to</span> <span class="n">the</span> <span class="n">top</span><span class="p">.</span>
<span class="o">--&gt;</span> <span class="mi">1</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">step</span>
<span class="o">--&gt;</span> <span class="mi">2</span> <span class="n">steps</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="mi">3</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">3</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">There</span> <span class="n">are</span> <span class="n">three</span> <span class="n">ways</span> <span class="n">to</span> <span class="n">climb</span> <span class="n">to</span> <span class="n">the</span> <span class="n">top</span><span class="p">.</span>
<span class="o">--&gt;</span> <span class="mi">1</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">step</span>
<span class="o">--&gt;</span> <span class="mi">1</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">2</span> <span class="n">steps</span>
<span class="o">--&gt;</span> <span class="mi">2</span> <span class="n">steps</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">step</span>
</code></pre></div></div>


</div>

<h3 id="brute-force-solution">Brute Force Solution</h3>

<p>At every step, we have two options: either climb <strong>1</strong> step or <strong>2</strong> steps.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">climbStairs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="c1"># we don't take any steps, so there is only 1 way
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="c1"># we can take one step to reach the end, and this is the only way
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>
        <span class="c1"># we can take one step twice or take two steps to reach the end
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">2</span>

        <span class="c1"># if we take one step, we are left with "n - 1" steps
</span>        <span class="n">take1step</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">climbStairs</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
        <span class="c1"># if we take two steps, we are left with "n - 2" steps
</span>        <span class="n">take2steps</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">climbStairs</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">take1step</span> <span class="o">+</span> <span class="n">take2steps</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(2<sup>N</sup>)</strong> because we are making <strong>2</strong> recursive calls in the same function.</p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong> which is used to store the recursion stack.</p>

<p>But can we do better? To be able to understand this, lets visualize the recursion stack.</p>

<p><img src="https://cdn.emre.me/2020-01-19-staircase.png" alt="Climbing Stairs" /></p>

<p>We can clearly see from colors that there are lots of <em>overlapping sub-problems</em> that we don’t need to calculate them again and again.</p>

<h3 id="top-down-dynamic-programming-with-memoization">Top-down Dynamic Programming with Memoization</h3>

<p>We can use an array to store already solved sub-problems.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">climbStairs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">dp</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">climbStairs_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="nf">climbStairs_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dp</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="c1"># we don't take any steps, so there is only 1 way
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="c1"># we can take one step to reach the end, and this is the only way
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>
        <span class="c1"># we can take one step twice or take two steps to reach the end
</span>        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">2</span>
        
        <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="c1"># if we take one step, we are left with "n - 1" steps
</span>            <span class="n">take1step</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">climbStairs_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
            <span class="c1"># if we take two steps, we are left with "n - 2" steps
</span>            <span class="n">take2steps</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">climbStairs_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
            
            <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">take1step</span> <span class="o">+</span> <span class="n">take2steps</span>
            
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N)</strong> because <a href="https://emre.me/algorithms/dynamic-programming/#memoization">memoization</a> array <code class="language-plaintext highlighter-rouge">dp[n+1]</code> stores the results of <strong>all</strong> <em>sub-problems</em>. We can conclude that we will not have more than <code class="language-plaintext highlighter-rouge">n + 1</code> <em>sub-problems</em>.</p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong> which is used to store the recursion stack.</p>

<h3 id="bottom-up-dynamic-programming-with-tabulation">Bottom-up Dynamic Programming with Tabulation</h3>

<p>Let’s try to populate our <code class="language-plaintext highlighter-rouge">dp[]</code> array in a bottom-up fashion. As we see from the recursion stack visualization, each <code class="language-plaintext highlighter-rouge">climbStairs(n)</code> call is the sum of the <strong>two</strong> previous calls.</p>

<p>We can use this fact while populating our <code class="language-plaintext highlighter-rouge">dp[]</code> array.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">climbStairs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">dp</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

        
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
        
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
</code></pre></div></div>
<p><strong>Time Complexity</strong>: <strong>O(N)</strong></p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong> which is used to store the recursion stack.</p>

<h3 id="memory-optimization">Memory Optimization</h3>

<p>As we can see from the visualization of the recursive stack and other solutions, to be able to calculate the <strong>n</strong>, you need the value of last two combinations: <strong>n-1</strong> and <strong>n-2</strong>.</p>

<p>These two values are enough and we don’t need to store all other past combinations.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">climbStairs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">2</span>

        <span class="n">first</span> <span class="o">=</span> <span class="mi">1</span>  <span class="c1"># how many step possibilities there are with 1 stairs
</span>        <span class="n">second</span> <span class="o">=</span> <span class="mi">2</span>  <span class="c1"># how many step possibilities there are with 2 stairs
</span>        <span class="n">third</span> <span class="o">=</span> <span class="mi">0</span>

        <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
            <span class="n">third</span> <span class="o">=</span> <span class="n">first</span> <span class="o">+</span> <span class="n">second</span>
            <span class="n">first</span> <span class="o">=</span> <span class="n">second</span>  <span class="c1"># walk up first to second
</span>            <span class="n">second</span> <span class="o">=</span> <span class="n">third</span>  <span class="c1"># walk up second to third
</span>        <span class="k">return</span> <span class="n">third</span>
</code></pre></div></div>

<p>OR more shortly;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">climbStairs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
            <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
        <span class="k">return</span> <span class="n">a</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N)</strong></p>

<p><strong>Space Complexity</strong>: <strong>O(1)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>

<p><a href="https://emre.me/coding-patterns/staircase">Staircase</a> pattern is very useful to solve <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> problems involving <em>minimum/maximum steps</em>, <em>jumps</em>, <em>stairs</em>, <em>fibonacci numbers</em> etc. to reach a target.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/unique-paths/">LeetCode 62 - Unique Paths [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/decode-ways/">LeetCode 91 - Decode Ways [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/fibonacci-number/">LeetCode 509 - Fibonacci Number [<em>easy</em>]</a></li>
  <li><a href="https://leetcode.com/problems/min-cost-climbing-stairs/">LeetCode 746 - Min Cost Climbing Stairs [<em>easy</em>]</a></li>
  <li><a href="https://leetcode.com/problems/number-of-dice-rolls-with-target-sum/">LeetCode 1155 - Number of Dice Rolls With Target Sum [<em>medium</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><category term="dynamic-programming" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Bitwise XOR</title><link href="https://emre.me/coding-patterns/bitwise-xor/" rel="alternate" type="text/html" title="Coding Patterns: Bitwise XOR" /><published>2019-12-11T00:00:00+03:00</published><updated>2019-12-11T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/bitwise-xor</id><content type="html" xml:base="https://emre.me/coding-patterns/bitwise-xor/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a>, <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a>, <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a> and <a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/bitwise-xor">Bitwise XOR</a> pattern which is very surprising to know the approaches that the <strong>XOR operator (^)</strong> enables us to solve certain problems.</p>

<p>If you are not familiar with <strong>binary computation</strong> and <strong>bit manipulation</strong>, I <em>strongly</em> recommend to read these <em>two</em> posts first:</p>

<ol>
  <li><a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/">Binary Computation and Bitwise Operators</a></li>
  <li><a href="https://emre.me/computer-science/bit-manipulation-tricks/">Bit Manipulation Tricks</a></li>
</ol>

<h2 id="problem-single-number">Problem: Single Number</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/single-number/"><strong>LeetCode 136 - Single Number</strong> [<em>easy</em>]</a></p>

<p>Given a non-empty array of integers, every element appears <strong>twice</strong> except for <em>one</em>. Find that <em>single one</em>.</p>

<p><strong>Note:</strong></p>

<p>Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">1</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">4</span>
</code></pre></div></div>


</div>

<h3 id="bitwise-xor-solution">Bitwise XOR Solution</h3>

<p>Recall the following two <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">properties of XOR</a>:</p>

<ol>
  <li>It returns <strong>0</strong> if we take <strong>XOR</strong> of <em>two same numbers</em>.</li>
  <li>It returns the <em>same number</em> if we <strong>XOR</strong> with <strong>0</strong>.</li>
</ol>

<p>So we can <strong>XOR</strong> all the numbers in the input; duplicate numbers will <em>zero</em> out each other and we will be left with the single number.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">singleNumber</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
            <span class="n">num</span> <span class="o">^=</span> <span class="n">i</span>
        <span class="k">return</span> <span class="n">num</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N)</strong> where <strong>N</strong> is the total number of elements in the input array.</p>

<p><strong>Space Complexity</strong>: <strong>O(1)</strong></p>

<h2 id="problem-single-number-iii">Problem: Single Number III</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/single-number-iii/"><strong>LeetCode 260 - Single Number III</strong> [<em>medium</em>]</a></p>

<p>Given an array of numbers <strong>nums</strong>, in which exactly <strong>two</strong> elements appear <em>only once</em> and all the other elements appear <em>exactly twice</em>. Find the two elements that appear <em>only once</em>.</p>

<p><strong>Example:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span>  <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Note:</strong></p>

<ul>
  <li>The order of the result is not important. So in the above example, <strong>[5, 3]</strong> is also correct.</li>
  <li>Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?</li>
</ul>


</div>

<h3 id="bitwise-xor-solution-1">Bitwise XOR Solution</h3>

<p>Let’s say <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code> are the two single numbers. If we do <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> of all elements of the given array, we will be left with <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> of <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code> as all other numbers will cancel each other because all of them appeared <em>twice</em>.</p>

<blockquote>
  <p>Since we now have <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> of <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code>, how can we find these two single numbers?</p>
</blockquote>

<p>As we know that <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code> are <strong>two different numbers</strong>, therefore, <em>they should have at least one bit different between them</em>!</p>

<p>If a bit in <code class="language-plaintext highlighter-rouge">n1xn2</code> is <strong>1</strong>, this means that <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code> have different bits in that place. We can take any bit which is <strong>1</strong> in <code class="language-plaintext highlighter-rouge">n1xn2</code> and partition all numbers in the given array into two groups based on that bit.</p>

<p>One group will have all those numbers with that bit set to <strong>0</strong> and the other with the bit set to <strong>1</strong>. This will ensure that <code class="language-plaintext highlighter-rouge">num1</code> will be in one group and <code class="language-plaintext highlighter-rouge">num2</code> will be in the other.</p>

<p>We can take <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> of all numbers in each group separately to get <code class="language-plaintext highlighter-rouge">num1</code> and <code class="language-plaintext highlighter-rouge">num2</code>, as all other numbers in each group will cancel each other.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">singleNumber</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>

        <span class="c1"># XOR of all numbers in the given list
</span>        <span class="n">n1xn2</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
            <span class="n">n1xn2</span> <span class="o">^=</span> <span class="n">num</span>

        <span class="c1"># rightmost bit which is 1
</span>        <span class="n">rightmost_bit</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">rightmost_bit</span> <span class="o">&amp;</span> <span class="n">n1xn2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">rightmost_bit</span> <span class="o">=</span> <span class="n">rightmost_bit</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span>

        <span class="n">num1</span><span class="p">,</span> <span class="n">num2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
        
        <span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">num</span> <span class="o">&amp;</span> <span class="n">rightmost_bit</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>  <span class="c1"># the bit is set
</span>                <span class="n">num1</span> <span class="o">^=</span> <span class="n">num</span>
            <span class="k">else</span><span class="p">:</span>  <span class="c1"># the bit is not set
</span>                <span class="n">num2</span> <span class="o">^=</span> <span class="n">num</span>

        <span class="k">return</span> <span class="p">[</span><span class="n">num1</span><span class="p">,</span> <span class="n">num2</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N)</strong> where <strong>N</strong> is the total number of elements in the input array.</p>

<p><strong>Space Complexity</strong>: <strong>O(1)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>
<p>Knowing <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> properties well opens some surprising doors in your problem solving skills. To be able to identify <a href="https://emre.me/computer-science/binary-computation-and-bitwise-operators/#xor-operator">XOR</a> related problems are mostly coming from previous experiences. But if you need to eliminate the same numbers from an integer array, using <a href="https://emre.me/computer-science/bit-manipulation-tricks/">Bit Manipulation Tricks</a> is extremely helpful.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/single-number-ii/">LeetCode 137 - Single Number II [<em>medium</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Topological Sort (Graph)</title><link href="https://emre.me/coding-patterns/topological-sort/" rel="alternate" type="text/html" title="Coding Patterns: Topological Sort (Graph)" /><published>2019-11-30T00:00:00+03:00</published><updated>2019-11-30T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/topological-sort</id><content type="html" xml:base="https://emre.me/coding-patterns/topological-sort/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a>, <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a> and <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a> pattern which is very useful for finding a linear ordering of elements that have dependencies on each other.</p>

<h2 id="problem-course-schedule">Problem: Course Schedule</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/course-schedule/"><strong>LeetCode 207 - Course Schedule</strong> [<em>medium</em>]</a></p>

<p>There are a total of <strong>n</strong> courses you have to take, labeled from <strong>0</strong> to <strong>n - 1</strong>.</p>

<p>Some courses may have prerequisites, for example to take course <strong>0</strong> you have to first take course <strong>1</strong>, which is expressed as a pair: <strong>[0, 1]</strong></p>

<p>Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span> 
<span class="n">Output</span><span class="p">:</span> <span class="n">true</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">There</span> <span class="n">are</span> <span class="n">a</span> <span class="n">total</span> <span class="n">of</span> <span class="mi">2</span> <span class="n">courses</span> <span class="n">to</span> <span class="n">take</span><span class="p">.</span> 
             <span class="n">To</span> <span class="n">take</span> <span class="n">course</span> <span class="mi">1</span> <span class="n">you</span> <span class="n">should</span> <span class="n">have</span> <span class="n">finished</span> <span class="n">course</span> <span class="mf">0.</span> <span class="n">So</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">possible</span><span class="p">.</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">Output</span><span class="p">:</span> <span class="n">false</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">There</span> <span class="n">are</span> <span class="n">a</span> <span class="n">total</span> <span class="n">of</span> <span class="mi">2</span> <span class="n">courses</span> <span class="n">to</span> <span class="n">take</span><span class="p">.</span> 
             <span class="n">To</span> <span class="n">take</span> <span class="n">course</span> <span class="mi">1</span> <span class="n">you</span> <span class="n">should</span> <span class="n">have</span> <span class="n">finished</span> <span class="n">course</span> <span class="mi">0</span><span class="p">,</span> <span class="ow">and</span> <span class="n">to</span> <span class="n">take</span> <span class="n">course</span> <span class="mi">0</span> 
             <span class="n">you</span> <span class="n">should</span> <span class="n">also</span> <span class="n">have</span> <span class="n">finished</span> <span class="n">course</span> <span class="mf">1.</span> <span class="n">So</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">impossible</span><span class="p">.</span>
</code></pre></div></div>

<p><strong>Note:</strong></p>

<ul>
  <li>The input <strong>prerequisites</strong> is a graph represented by a list of <strong>edges</strong>, not adjacency matrices. Read more about how a <a href="https://emre.me/data-structures/graphs/">graph</a> is represented.</li>
  <li>You may assume that there are no duplicate <strong>edges</strong> in the input <strong>prerequisites</strong>.</li>
</ul>


</div>

<h3 id="topological-sort-solution">Topological Sort Solution</h3>

<p>The aim of <a href="https://en.wikipedia.org/wiki/Topological_sorting">topological sort</a> is to provide a partial ordering among the <em><a href="https://emre.me/data-structures/graphs/#vertex">vertices</a></em> of the <a href="https://emre.me/data-structures/graphs/">graph</a> such that if there is an <em><a href="https://emre.me/data-structures/graphs/#edge">edge</a></em> from <code class="language-plaintext highlighter-rouge">U</code> to <code class="language-plaintext highlighter-rouge">V</code> then <code class="language-plaintext highlighter-rouge">U &lt;= V</code>, which means, <code class="language-plaintext highlighter-rouge">U</code> comes before <code class="language-plaintext highlighter-rouge">V</code> in the ordering.</p>

<ol>
  <li><strong>Source:</strong> Any node that has <em>no incoming edge</em> and has <em>only outgoing edges</em> is called a <strong>source</strong>.</li>
  <li><strong>Sink:</strong> Any node that has <em>only incoming edges</em> and <em>no outgoing edge</em> is called a <strong>sink</strong>.</li>
  <li>Topological ordering <em>starts</em> with one of the <strong>sources</strong> and <em>ends</em> at one of the <strong>sinks</strong>.</li>
  <li>A topological ordering is possible only when the graph has no <a href="https://emre.me/data-structures/graphs/#directed-or-undirected">directed cycles</a>, i.e. if the graph is a <a href="https://emre.me/data-structures/graphs/#cyclic-or-acyclic">Directed Acyclic Graph (DAG)</a>. If the graph has a <strong>cycle</strong>, some vertices will have <em>cyclic dependencies</em> which makes it <strong>impossible</strong> to find a linear ordering among vertices.</li>
</ol>

<p>To find the <a href="https://en.wikipedia.org/wiki/Topological_sorting">topological sort</a> of a <a href="https://emre.me/data-structures/graphs/">graph</a> we can <em>traverse</em> the graph in a <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a> way.</p>

<p><strong>a. Initialization</strong></p>

<p>We will store the graph in <a href="https://emre.me/data-structures/graphs/#adjacency-list">Adjacency Lists</a>, which means each parent <a href="https://emre.me/data-structures/graphs/#vertex">vertex</a> will have a list containing all of its children. We will do this using a <a href="https://emre.me/data-structures/hash-tables/">Hash Table</a> where the <code class="language-plaintext highlighter-rouge">key</code> will be the <em>parent vertex number</em> and the <code class="language-plaintext highlighter-rouge">value</code> will be a <a href="https://emre.me/data-structures/lists/">List</a> containing <em>children vertices</em>.</p>

<p>To find the sources, we will keep a <a href="https://emre.me/data-structures/hash-tables/">Hash Table</a> to count the in-degrees (count of incoming edges of each vertex). Any vertex with <strong>0</strong> in-degree will be a <strong>source</strong>.</p>

<p><strong>b. Build the graph and find in-degrees of all vertices</strong></p>

<p>We will build the graph from the input and populate the in-degrees <a href="https://emre.me/data-structures/hash-tables/">Hash Table</a>.</p>

<p><strong>c. Find all sources</strong></p>

<p>All vertices with <strong>0</strong> in-degrees will be our sources and we will store them in a <a href="https://emre.me/data-structures/stacks-and-queues/#queues">Queue</a>.</p>

<p><strong>d. Sort</strong></p>

<p>For each source:</p>
<ul>
  <li>Add it to the sorted list.</li>
  <li>Get all of its children from the <a href="https://emre.me/data-structures/graphs/">graph</a>.</li>
  <li>Decrement the in-degree of each child by <strong>1</strong>.</li>
  <li>If a child’s in-degree becomes <strong>0</strong>, add it to the sources <a href="https://emre.me/data-structures/stacks-and-queues/#queues">Queue</a>.</li>
</ul>

<p>Repeat these steps, until the source <a href="https://emre.me/data-structures/stacks-and-queues/#queues">Queue</a> is empty.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">canFinish</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">numCourses</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">prerequisites</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
        <span class="n">sorted_list</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">if</span> <span class="n">numCourses</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>

        <span class="c1"># a. Initialization
</span>        <span class="n">graph</span> <span class="o">=</span> <span class="p">{</span><span class="n">i</span><span class="p">:</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">numCourses</span><span class="p">)}</span>  <span class="c1"># adjacency list graph
</span>        <span class="n">in_degree</span> <span class="o">=</span> <span class="p">{</span><span class="n">i</span><span class="p">:</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">numCourses</span><span class="p">)}</span>  <span class="c1"># count of incoming edges
</span>
        <span class="c1"># b. Build the graph
</span>        <span class="k">for</span> <span class="n">prerequisite</span> <span class="ow">in</span> <span class="n">prerequisites</span><span class="p">:</span>
            <span class="n">parent</span><span class="p">,</span> <span class="n">child</span> <span class="o">=</span> <span class="n">prerequisite</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">prerequisite</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">graph</span><span class="p">[</span><span class="n">parent</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>  <span class="c1"># put the child into it's parent's list
</span>            <span class="n">in_degree</span><span class="p">[</span><span class="n">child</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="c1"># c. Find all sources
</span>        <span class="n">sources</span> <span class="o">=</span> <span class="n">deque</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">in_degree</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">in_degree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">sources</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>

        <span class="c1"># d. Sort
</span>        <span class="k">while</span> <span class="n">sources</span><span class="p">:</span>
            <span class="n">vertex</span> <span class="o">=</span> <span class="n">sources</span><span class="p">.</span><span class="n">popleft</span><span class="p">()</span>
            <span class="n">sorted_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">vertex</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">vertex</span><span class="p">]:</span>  <span class="c1"># get the node's children to decrement their in-degrees
</span>                <span class="n">in_degree</span><span class="p">[</span><span class="n">child</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">in_degree</span><span class="p">[</span><span class="n">child</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">sources</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>

        <span class="c1"># if sorted_list does not contain all the courses, there is a cyclic dependency between courses
</span>        <span class="c1"># scheduling is not possible if there is a cyclic dependency
</span>        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="n">sorted_list</span><span class="p">)</span> <span class="o">==</span> <span class="n">numCourses</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(V + E)</strong> where <strong>V</strong> is the total number of courses and <strong>E</strong> is the total number of <code class="language-plaintext highlighter-rouge">prerequisites</code>.</p>

<p><strong>Space Complexity</strong>: <strong>O(V + E)</strong> since we are storing all of the <code class="language-plaintext highlighter-rouge">prerequisites</code> for each course in an <a href="https://emre.me/data-structures/graphs/#adjacency-list">adjacency list</a>.</p>

<h2 id="how-to-identify">How to identify?</h2>

<p><a href="https://emre.me/coding-patterns/topological-sort">Topological Sort</a> pattern is very useful for finding a linear ordering of elements that have dependencies on each other.</p>

<p>Scheduling or grouping problems which have dependencies between items are good examples to the problems that can be solved with using this technique.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/course-schedule-ii/">LeetCode 210 - Course Schedule II [<em>medium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/alien-dictionary/">LeetCode 269 - Alien Dictionary [<em>hard</em>] [<em>premium</em>]</a></li>
  <li><a href="https://leetcode.com/problems/minimum-height-trees/">LeetCode 310 - Minimum Height Trees [<em>medium</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><category term="graphs" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: 0/1 Knapsack (DP)</title><link href="https://emre.me/coding-patterns/knapsack/" rel="alternate" type="text/html" title="Coding Patterns: 0/1 Knapsack (DP)" /><published>2019-11-29T00:00:00+03:00</published><updated>2019-11-29T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/knapsack</id><content type="html" xml:base="https://emre.me/coding-patterns/knapsack/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a>, <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a> and <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a> pattern which is very useful to solve the famous <a href="https://en.wikipedia.org/wiki/Knapsack_problem">Knapsack problem</a> by using <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> techniques.</p>

<p>We are going to use <strong>top-down</strong> <a href="https://emre.me/algorithms/dynamic-programming/#memoization">Memoisation</a> or <strong>bottom-up</strong> <a href="https://emre.me/algorithms/dynamic-programming/#tabulation">Tabulation</a> technique to solve the problems efficiently.</p>

<h2 id="problem-partition-equal-subset-sum">Problem: Partition Equal Subset Sum</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/partition-equal-subset-sum/"><strong>LeetCode 416 - Partition Equal Subset Sum</strong> [<em>medium</em>]</a></p>

<p>Given a <em>non-empty</em> array containing only <strong>positive</strong> integers, find if the array can be partitioned into <em>two subsets</em> such that the <strong>sum</strong> of elements in both subsets is <strong>equal</strong>.</p>

<p><strong>Note:</strong></p>

<p>Each of the array element will not exceed <strong>100</strong>. The array size will not exceed <strong>200</strong>.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="n">true</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">The</span> <span class="n">array</span> <span class="n">can</span> <span class="n">be</span> <span class="n">partitioned</span> <span class="k">as</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span> <span class="ow">and</span> <span class="p">[</span><span class="mi">11</span><span class="p">].</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="n">false</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="n">The</span> <span class="n">array</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">partitioned</span> <span class="n">into</span> <span class="n">equal</span> <span class="nb">sum</span> <span class="n">subsets</span><span class="p">.</span>
</code></pre></div></div>


</div>

<h3 id="brute-force-solution">Brute Force Solution</h3>

<p>A basic <em>brute-force</em> solution could be to try <strong>all</strong> combinations of partitioning the given numbers into <strong>two</strong> sets to see if any pair of sets has an equal sum.</p>

<p>This essentially transforms our problem to: Find a subset of the given numbers that has a total sum of <code class="language-plaintext highlighter-rouge">sum / 2</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">canPartition</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
        <span class="n">s</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">s</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
        
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">s</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="nf">can_partition_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span><span class="p">,</span> <span class="n">current_index</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">sum</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">True</span>
        
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">current_index</span> <span class="o">&gt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
            <span class="k">return</span> <span class="bp">False</span>
        
        <span class="k">if</span> <span class="n">nums</span><span class="p">[</span><span class="n">current_index</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="nb">sum</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">current_index</span><span class="p">],</span> <span class="n">current_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)):</span>
                <span class="k">return</span> <span class="bp">True</span>
        
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span><span class="p">,</span> <span class="n">current_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(2<sup>N</sup>)</strong> where <strong>N</strong> represents the total number.</p>

<p><strong>Space Complexity</strong>: <strong>O(N)</strong> which will be used to store recursion stack.</p>

<h3 id="top-down-dynamic-programming-with-memoization">Top-down Dynamic Programming with Memoization</h3>

<p>We can use <a href="https://emre.me/algorithms/dynamic-programming/#memoization">memoization</a> to overcome the overlapping sub-problems. Since we need to store the results for <em>every</em> subset and for <em>every</em> possible <code class="language-plaintext highlighter-rouge">sum</code>, therefore we will be using a <strong>two-dimensional array</strong> to store the results of the solved sub-problems.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">canPartition</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
        <span class="n">s</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">s</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
        
        <span class="c1"># initialize two-dimensional dp array, -1 for default
</span>        <span class="n">dp</span> <span class="o">=</span> <span class="p">[[</span><span class="o">-</span><span class="mi">1</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span> <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">))]</span>
        
        <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span> <span class="o">/</span> <span class="mi">2</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">True</span>  <span class="c1"># return True for 1
</span>        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>  <span class="c1"># return False for 0
</span>        
    <span class="k">def</span> <span class="nf">can_partition_recursive</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dp</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span><span class="p">,</span> <span class="n">current_index</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">sum</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">1</span>
        
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">current_index</span> <span class="o">&gt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
            <span class="k">return</span> <span class="mi">0</span>
        
        <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">current_index</span><span class="p">][</span><span class="nb">sum</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>  <span class="c1"># if we have not processed this sub-problem
</span>                <span class="k">if</span> <span class="n">nums</span><span class="p">[</span><span class="n">current_index</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="nb">sum</span><span class="p">:</span>
                    <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">current_index</span><span class="p">],</span> <span class="n">current_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
                        <span class="n">dp</span><span class="p">[</span><span class="n">current_index</span><span class="p">][</span><span class="nb">sum</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
                        <span class="k">return</span> <span class="mi">1</span>

                <span class="c1"># recursive call after excluding the number at the current_index
</span>                <span class="n">dp</span><span class="p">[</span><span class="n">current_index</span><span class="p">][</span><span class="nb">sum</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">can_partition_recursive</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="nb">sum</span><span class="p">,</span> <span class="n">current_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">current_index</span><span class="p">][</span><span class="nb">sum</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N * S)</strong> where <strong>N</strong> represents the total numbers and <strong>S</strong> is the total sum of all numbers.</p>

<p><strong>Space Complexity</strong>: <strong>O(N * S)</strong></p>

<h3 id="bottom-up-dynamic-programming-with-tabulation">Bottom-up Dynamic Programming with Tabulation</h3>

<p>Let’s try to populate our <code class="language-plaintext highlighter-rouge">dp[][]</code> array from the above solution by working in a <strong>bottom-up</strong> fashion with using <a href="https://emre.me/algorithms/dynamic-programming/#tabulation">tabulation</a> dynamic programming technique.</p>

<p>Essentially, we want to find if we can make all possible <code class="language-plaintext highlighter-rouge">sum</code> with every subset. This means, <code class="language-plaintext highlighter-rouge">dp[i][s]</code> will be <code class="language-plaintext highlighter-rouge">True</code> if we can make the sum <strong><code class="language-plaintext highlighter-rouge">s</code></strong> from the first <strong><code class="language-plaintext highlighter-rouge">i</code></strong> numbers.</p>

<p>For each number at index <strong><code class="language-plaintext highlighter-rouge">i</code></strong> and sum <strong><code class="language-plaintext highlighter-rouge">s</code></strong>, we have these two options:</p>

<ol>
  <li>Exclude the number. In this case, we will see if we can get <strong><code class="language-plaintext highlighter-rouge">s</code></strong> from the subset excluding this number: <code class="language-plaintext highlighter-rouge">dp[i-1][s]</code></li>
  <li>Include the number if its value is not more than <strong><code class="language-plaintext highlighter-rouge">s</code></strong>. In this case, we will see if we can find a subset to get the remaining sum: <code class="language-plaintext highlighter-rouge">dp[i-1][s-num[i]]</code></li>
</ol>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">canPartition</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
        <span class="n">s</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">s</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
        
        <span class="n">s</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
        <span class="n">dp</span> <span class="o">=</span> <span class="p">[[</span><span class="bp">False</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">))]</span>
        
        <span class="c1"># populate s = 0 columns
</span>        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
            
        <span class="c1"># form a subset only when the required sum is equal to its value
</span>        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">s</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">j</span>
        
        <span class="c1"># process all subsets for all sums
</span>        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">s</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
                <span class="c1"># if we can get the sum 'j' without the number at index 'i'
</span>                <span class="k">if</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]:</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
                    
                <span class="c1"># else if we can find a subset to get the remaining sum
</span>                <span class="k">elif</span> <span class="n">j</span> <span class="o">&gt;=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span>
        
        <span class="c1"># the bottom-right corner will have our answer
</span>        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">s</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N * S)</strong> where <strong>N</strong> represents the total numbers and <strong>S</strong> is the total sum of all numbers.</p>

<p><strong>Space Complexity</strong>: <strong>O(N * S)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>

<p><a href="https://emre.me/coding-patterns/knapsack">0/1 Knapsack</a> pattern is very useful to solve the famous <a href="https://en.wikipedia.org/wiki/Knapsack_problem">Knapsack problem</a> by using <a href="https://emre.me/algorithms/dynamic-programming/">Dynamic Programming</a> techniques.</p>

<p><a href="https://en.wikipedia.org/wiki/Knapsack_problem">Knapsack problem</a> is all about optimization. For example, given a set of items, each with a <strong>weight</strong> and a <strong>value</strong>, determine the number of each item to include in a collection so that the total weight is <em>less than or equal to</em> a given limit and the total value is <em>as large as possible</em>.</p>

<p>We are using <strong>top-down</strong> <a href="https://emre.me/algorithms/dynamic-programming/#memoization">Memoisation</a> or <strong>bottom-up</strong> <a href="https://emre.me/algorithms/dynamic-programming/#tabulation">Tabulation</a> technique to solve these problems efficiently.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/ones-and-zeroes/">LeetCode 474 - Ones and Zeroes [<em>medium</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><category term="dynamic-programming" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: K-way Merge</title><link href="https://emre.me/coding-patterns/k-way-merge/" rel="alternate" type="text/html" title="Coding Patterns: K-way Merge" /><published>2019-11-22T00:00:00+03:00</published><updated>2019-11-22T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/k-way-merge</id><content type="html" xml:base="https://emre.me/coding-patterns/k-way-merge/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a>, <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a> and <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a> pattern which is very useful to solve the problems whenever we are given <strong>K</strong> sorted arrays, we can use a <a href="https://emre.me/data-structures/heaps/">Heap</a> to efficiently perform a <em>sorted traversal</em> of <em>all</em> the elements of <em>all</em> arrays.</p>

<p>We can push the <strong>smallest</strong> (<em>first</em>) element of each sorted array in a <a href="https://emre.me/data-structures/heaps/#min_heapify-and-build_min_heap">Min Heap</a> to get the overall minimum. While inserting elements to the <a href="https://emre.me/data-structures/heaps/#min_heapify-and-build_min_heap">Min Heap</a> we keep track of which array the element came from.</p>

<p>We can also remove the <strong>top</strong> element from the <a href="https://emre.me/data-structures/heaps/">heap</a> to get the <em>smallest</em> element and push the next element from the same array, to which this <em>smallest</em> element belonged, to the <a href="https://emre.me/data-structures/heaps/">heap</a>. We can repeat this process to make a sorted traversal of all elements.</p>

<h2 id="problem-merge-k-sorted-lists">Problem: Merge K Sorted Lists</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/merge-k-sorted-lists/"><strong>LeetCode 23 - Merge k Sorted Lists</strong> [<em>hard</em>]</a></p>

<p>Merge <strong>k</strong> sorted linked lists and return it as one sorted list. Analyze and describe its complexity.</p>

<p><strong>Example:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span>
<span class="p">[</span>
  <span class="mi">1</span><span class="o">-&gt;</span><span class="mi">4</span><span class="o">-&gt;</span><span class="mi">5</span><span class="p">,</span>
  <span class="mi">1</span><span class="o">-&gt;</span><span class="mi">3</span><span class="o">-&gt;</span><span class="mi">4</span><span class="p">,</span>
  <span class="mi">2</span><span class="o">-&gt;</span><span class="mi">6</span>
<span class="p">]</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">1</span><span class="o">-&gt;</span><span class="mi">1</span><span class="o">-&gt;</span><span class="mi">2</span><span class="o">-&gt;</span><span class="mi">3</span><span class="o">-&gt;</span><span class="mi">4</span><span class="o">-&gt;</span><span class="mi">4</span><span class="o">-&gt;</span><span class="mi">5</span><span class="o">-&gt;</span><span class="mi">6</span>
</code></pre></div></div>


</div>

<h3 id="k-way-merge-solution">K-way Merge Solution</h3>

<p>We need to find the <strong>smallest</strong> element of <strong>all</strong> the input lists. To do so, we have to compare only the <strong>smallest</strong> element of all the lists first. Once we have the <em>smallest</em> element, we can put it in the merged list.</p>

<p>Following a similar pattern, we can then find the <em>next smallest</em> element of all the lists to add it to the merged list.</p>

<ol>
  <li>We can push the <strong>smallest</strong> (<em>first</em>) element of each sorted array in a <a href="https://emre.me/data-structures/heaps/#min_heapify-and-build_min_heap">Min Heap</a> to get the overall minimum.</li>
  <li>After this, we can take out the <strong>smallest</strong> (top) element from the <a href="https://emre.me/data-structures/heaps/">heap</a> and add it to the merged list.</li>
  <li>After removing the <strong>smallest</strong> element from the <a href="https://emre.me/data-structures/heaps/">heap</a>, we can insert the <em>next</em> element of the same list into the <a href="https://emre.me/data-structures/heaps/">heap</a>.</li>
  <li>We can repeat steps <strong>2</strong> and <strong>3</strong> to populate the merged list in sorted order.</li>
</ol>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">ListNode</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">val</span> <span class="o">=</span> <span class="n">x</span>
        <span class="bp">self</span><span class="p">.</span><span class="nb">next</span> <span class="o">=</span> <span class="bp">None</span>


<span class="k">class</span> <span class="nc">ListNodeExtension</span><span class="p">(</span><span class="n">ListNode</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">val</span> <span class="o">&lt;</span> <span class="n">other</span><span class="p">.</span><span class="n">val</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">mergeKLists</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lists</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">ListNode</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">ListNode</span><span class="p">:</span>
        <span class="n">ListNode</span><span class="p">.</span><span class="n">__lt__</span> <span class="o">=</span> <span class="n">ListNodeExtension</span><span class="p">.</span><span class="n">__lt__</span>
        <span class="n">min_heap</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">root</span> <span class="ow">in</span> <span class="n">lists</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">root</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
                <span class="n">heappush</span><span class="p">(</span><span class="n">min_heap</span><span class="p">,</span> <span class="n">root</span><span class="p">)</span>

        <span class="n">head</span> <span class="o">=</span> <span class="n">tail</span> <span class="o">=</span> <span class="n">ListNode</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="k">while</span> <span class="n">min_heap</span><span class="p">:</span>
            <span class="n">tail</span><span class="p">.</span><span class="nb">next</span> <span class="o">=</span> <span class="n">heappop</span><span class="p">(</span><span class="n">min_heap</span><span class="p">)</span>
            <span class="n">tail</span> <span class="o">=</span> <span class="n">tail</span><span class="p">.</span><span class="nb">next</span>
            <span class="k">if</span> <span class="n">tail</span><span class="p">.</span><span class="nb">next</span><span class="p">:</span>
                <span class="n">heappush</span><span class="p">(</span><span class="n">min_heap</span><span class="p">,</span> <span class="n">tail</span><span class="p">.</span><span class="nb">next</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">head</span><span class="p">.</span><span class="nb">next</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N log K)</strong> where <strong>N</strong> is the total number of elements in all the <strong>K</strong> input arrays.</p>

<p><strong>Space Complexity</strong>: <strong>O(K)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>
<p>If the problem giving <strong>K</strong> sorted arrays and asks us to perform a <em>sorted traversal</em> of <em>all</em> the elements of <em>all</em> arrays, we need to think about <a href="https://emre.me/coding-patterns/k-way-merge">K-way Merge</a> pattern.</p>

<p>While solving the problems, we are going to use <a href="https://emre.me/data-structures/heaps/">Heap</a> data structure to keep track of all elements in <strong>K</strong> arrays.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/median-of-two-sorted-arrays/">LeetCode 4 - Median of Two Sorted Arrays [<em>hard</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Top K Numbers</title><link href="https://emre.me/coding-patterns/top-k-numbers/" rel="alternate" type="text/html" title="Coding Patterns: Top K Numbers" /><published>2019-11-21T00:00:00+03:00</published><updated>2019-11-21T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/top-k-numbers</id><content type="html" xml:base="https://emre.me/coding-patterns/top-k-numbers/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a>, <a href="https://emre.me/coding-patterns/subsets/">Subsets</a> and <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a> pattern which is very useful to solve the problems that asks us to find the <em>top</em> / <em>smallest</em> / <em>frequent</em> <strong>K</strong> elements among a given set.</p>

<p>We are going to use <a href="https://emre.me/data-structures/heaps/">Heap</a> data structure to keep track of <strong>K</strong> elements.</p>

<h2 id="problem-k-th-largest-element">Problem: K-th Largest Element</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/kth-largest-element-in-an-array/"><strong>LeetCode 215 - Kth Largest Element in an Array</strong> [<em>medium</em>]</a></p>

<p>Find the <strong>k</strong>th largest element in an unsorted array. Note that it is the <strong>k</strong>th largest element in the sorted order, not the <strong>k</strong>th distinct element.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span> <span class="ow">and</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">5</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span> <span class="ow">and</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">4</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">4</span>
</code></pre></div></div>

<p><strong>Note:</strong></p>

<p>You may assume <strong>k</strong> is always valid, 1 ≤ <strong>k</strong> ≤ array’s length.</p>


</div>

<h3 id="top-k-numbers-solution">Top K Numbers Solution</h3>

<p>The best data structure to keep track of top <strong>K</strong> elements is <a href="https://emre.me/data-structures/heaps/">Heap</a>.</p>

<p>If we iterate through the array one element at a time and keep <strong>k</strong>th largest element in a <a href="https://emre.me/data-structures/heaps/">heap</a> such that each time we find a <em>larger</em> number than the <em>smallest</em> number in the <a href="https://emre.me/data-structures/heaps/">heap</a>, we do two things:</p>

<ol>
  <li>Take out the <strong>smallest</strong> number from the heap</li>
  <li>Insert the <strong>larger</strong> number into the heap</li>
</ol>

<p>This will ensure that we always have top <strong>k</strong> largest numbers in the <a href="https://emre.me/data-structures/heaps/">heap</a>. We will use a <a href="https://emre.me/data-structures/heaps/#min_heapify-and-build_min_heap">min-heap</a> for this;</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">heapq</span> <span class="kn">import</span> <span class="o">*</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">findKthLargest</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">],</span> <span class="n">k</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">min_heap</span> <span class="o">=</span> <span class="p">[]</span>
        
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">k</span><span class="p">):</span>
            <span class="n">heappush</span><span class="p">(</span><span class="n">min_heap</span><span class="p">,</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
        
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
            <span class="k">if</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">min_heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
                <span class="n">heappop</span><span class="p">(</span><span class="n">min_heap</span><span class="p">)</span>
                <span class="n">heappush</span><span class="p">(</span><span class="n">min_heap</span><span class="p">,</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
            
        <span class="k">return</span> <span class="n">min_heap</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(N log K)</strong>.</p>

<p><strong>Space Complexity</strong>: <strong>O(K)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>
<p>If the problem asking us to find the <em>top</em> / <em>smallest</em> / <em>frequent</em> <strong>K</strong> elements among a given set, we need to think about <a href="https://emre.me/coding-patterns/top-k-numbers">Top K Numbers</a> pattern.</p>

<p>While solving the problems, we are going to use <a href="https://emre.me/data-structures/heaps/">Heap</a> data structure to keep track of <strong>K</strong> elements.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/k-closest-points-to-origin/">LeetCode 973 - K Closest Points to Origin [<em>medium</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry><entry><title type="html">Coding Patterns: Modified Binary Search</title><link href="https://emre.me/coding-patterns/modified-binary-search/" rel="alternate" type="text/html" title="Coding Patterns: Modified Binary Search" /><published>2019-11-20T00:00:00+03:00</published><updated>2019-11-20T00:00:00+03:00</updated><id>https://emre.me/coding-patterns/modified-binary-search</id><content type="html" xml:base="https://emre.me/coding-patterns/modified-binary-search/"><![CDATA[<p>In <strong><a href="https://emre.me/categories/#coding-patterns">Coding Patterns</a></strong> series, we will try to <em>recognize</em> common patterns <em>underlying</em> behind each algorithm question, using real examples from <a href="https://leetcode.com/">Leetcode</a>.</p>

<p>Previous posts were about <a href="https://emre.me/coding-patterns/sliding-window/">Sliding Window</a>, <a href="https://emre.me/coding-patterns/two-pointers/">Two Pointers</a>, <a href="https://emre.me/coding-patterns/fast-slow-pointers/">Fast &amp; Slow Pointers</a>, <a href="https://emre.me/coding-patterns/merge-intervals/">Merge Intervals</a>, <a href="https://emre.me/coding-patterns/cyclic-sort/">Cyclic Sort</a>, <a href="https://emre.me/coding-patterns/in-place-reversal-of-a-linked-list/">In-place Reversal of a Linked List</a>, <a href="https://emre.me/coding-patterns/breadth-first-search/">Breadth First Search (BFS)</a>, <a href="https://emre.me/coding-patterns/depth-first-search/">Depth First Search (DFS)</a>, <a href="https://emre.me/coding-patterns/two-heaps/">Two Heaps</a> and <a href="https://emre.me/coding-patterns/subsets/">Subsets</a> patterns and today, we will introduce <a href="https://emre.me/coding-patterns/modified-binary-search/">Modified Binary Search</a> pattern which is very useful to solve the problems whenever we are given a sorted <a href="https://emre.me/data-structures/lists/">Array</a> or <a href="https://emre.me/data-structures/linked-lists/">Linked List</a> or Matrix, and we are asked to find a certain element.</p>

<p>This pattern describes an efficient way to handle all problems involving <a href="https://emre.me/data-structures/binary-search-trees/">Binary Search</a>.</p>

<h2 id="problem-binary-search">Problem: Binary Search</h2>

<div class="notice--info">
  
<p><a href="https://leetcode.com/problems/binary-search/"><strong>LeetCode 704 - Binary Search</strong> [<em>easy</em>]</a></p>

<p>Given a sorted (in ascending order) integer array <code class="language-plaintext highlighter-rouge">nums</code> of <strong>n</strong> elements and a <code class="language-plaintext highlighter-rouge">target</code> value, write a function to search <code class="language-plaintext highlighter-rouge">target</code> in <code class="language-plaintext highlighter-rouge">nums</code>. If <code class="language-plaintext highlighter-rouge">target</code> exists, then return its index, otherwise return <strong>-1</strong>.</p>

<p><strong>Example 1:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">9</span>
<span class="n">Output</span><span class="p">:</span> <span class="mi">4</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="mi">9</span> <span class="n">exists</span> <span class="ow">in</span> <span class="n">nums</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">index</span> <span class="ow">is</span> <span class="mi">4</span>
</code></pre></div></div>

<p><strong>Example 2:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Input</span><span class="p">:</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">],</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">Output</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span>
<span class="n">Explanation</span><span class="p">:</span> <span class="mi">2</span> <span class="n">does</span> <span class="ow">not</span> <span class="n">exist</span> <span class="ow">in</span> <span class="n">nums</span> <span class="n">so</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
</code></pre></div></div>

<p><strong>Note:</strong></p>

<ul>
  <li>You may assume that all elements in <code class="language-plaintext highlighter-rouge">nums</code> are unique.</li>
  <li><strong>n</strong> will be in the <code class="language-plaintext highlighter-rouge">range [1, 10000]</code>.</li>
  <li>The value of each element in <code class="language-plaintext highlighter-rouge">nums</code> will be in the <code class="language-plaintext highlighter-rouge">range [-9999, 9999]</code>.</li>
</ul>


</div>

<h3 id="binary-search-solution">Binary Search Solution</h3>

<p><strong>1-</strong> Let’s assume that <code class="language-plaintext highlighter-rouge">start</code> is the first element and <code class="language-plaintext highlighter-rouge">end</code> is the last element in <code class="language-plaintext highlighter-rouge">nums</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">end</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
</code></pre></div></div>

<p><strong>2-</strong> We need to find middle value, <code class="language-plaintext highlighter-rouge">mid</code>. An easy way to do it in <a href="https://www.python.org/">Python</a> is</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">start</span> <span class="o">+</span> <span class="n">end</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
</code></pre></div></div>

<p>For <a href="https://www.java.com/">Java</a> and <a href="https://isocpp.org/">C++</a>, this equation will work for most cases, but when <code class="language-plaintext highlighter-rouge">start</code> or <code class="language-plaintext highlighter-rouge">end</code> is <em>large</em>, this equation will give us the wrong result due to <em>integer overflow</em>. To solve this problem, we will do our calculation a bit differently;</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">start</span> <span class="o">+</span> <span class="o">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="o">)</span> <span class="o">/</span> <span class="mi">2</span><span class="o">;</span>
</code></pre></div></div>

<p><strong>3-</strong> Next, we will see if the <code class="language-plaintext highlighter-rouge">target</code> value is equal to the number at <code class="language-plaintext highlighter-rouge">mid</code> value. If it is equal we return <code class="language-plaintext highlighter-rouge">mid</code> as the required index.</p>

<p><strong>4-</strong> If <code class="language-plaintext highlighter-rouge">target</code> is not equal to number at index <code class="language-plaintext highlighter-rouge">mid</code>, there are two possibilities that we need to check:</p>

<ul>
  <li>
    <p>If <code class="language-plaintext highlighter-rouge">target &lt; nums[mid]</code>, then we can conclude that <code class="language-plaintext highlighter-rouge">target</code> will be <strong>smaller</strong> than all the numbers after index <code class="language-plaintext highlighter-rouge">mid</code> as the array is sorted in the ascending order. We can reduce our search to <code class="language-plaintext highlighter-rouge">end = mid - 1</code>.</p>
  </li>
  <li>
    <p>If <code class="language-plaintext highlighter-rouge">target &gt; nums[mid]</code>, then we can conclude that <code class="language-plaintext highlighter-rouge">target</code> will be <strong>greater</strong> than all numbers before index <code class="language-plaintext highlighter-rouge">mid</code> as the array is sorted in the ascending order. We can reduce our search to <code class="language-plaintext highlighter-rouge">start = mid + 1</code>.</p>
  </li>
</ul>

<p><img src="https://cdn.emre.me/2019-08-08-binary-search.png" alt="Binary Search" class="align-center" /></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>


<span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nums</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">],</span> <span class="n">target</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
        <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">end</span><span class="p">:</span>
            <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">start</span> <span class="o">+</span> <span class="n">end</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>

            <span class="k">if</span> <span class="n">target</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">mid</span><span class="p">]:</span>
                <span class="k">return</span> <span class="n">mid</span>

            <span class="k">if</span> <span class="n">target</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">mid</span><span class="p">]:</span>
                <span class="n">end</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">start</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
</code></pre></div></div>

<p><strong>Time Complexity</strong>: <strong>O(log N)</strong> where <strong>N</strong> is the total elements in the given array.</p>

<p><strong>Space Complexity</strong>: <strong>O(1)</strong></p>

<h2 id="how-to-identify">How to identify?</h2>

<p>This approach is quite useful to solve the problems whenever we are given a sorted <a href="https://emre.me/data-structures/lists/">Array</a> or <a href="https://emre.me/data-structures/linked-lists/">Linked List</a> or Matrix, and we are asked to find a certain element.</p>

<p>This pattern describes an efficient way to handle all problems involving <a href="https://emre.me/data-structures/binary-search-trees/">Binary Search</a>.</p>

<h2 id="similar-leetcode-problems">Similar LeetCode Problems</h2>
<ul>
  <li><a href="https://leetcode.com/problems/find-smallest-letter-greater-than-target/">LeetCode 744 - Find Smallest Letter Greater Than Target [<em>easy</em>]</a></li>
</ul>]]></content><author><name>Emre Bolat</name><email>emre@emre.me</email></author><category term="coding-patterns" /><category term="algorithms" /><category term="python" /><summary type="html"><![CDATA[In Coding Patterns series, we will try to recognize common patterns underlying behind each algorithm question, using real examples from Leetcode.]]></summary></entry></feed>