<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Your DevOps Guy</title>
    <description>The latest articles on DEV Community by Your DevOps Guy (@codinglanguages).</description>
    <link>https://dev.to/codinglanguages</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F411085%2F97864531-4303-4c2f-8d9a-1d0808318814.png</url>
      <title>DEV Community: Your DevOps Guy</title>
      <link>https://dev.to/codinglanguages</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codinglanguages"/>
    <language>en</language>
    <item>
      <title>SPL - Structured Programming Language</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Wed, 29 Mar 2023 12:33:04 +0000</pubDate>
      <link>https://dev.to/codinglanguages/spl-structured-programming-language-5g7g</link>
      <guid>https://dev.to/codinglanguages/spl-structured-programming-language-5g7g</guid>
      <description>&lt;p&gt;Do you know there is live beyond SQL? In this post I'm going to show you an interesting alternative.&lt;/p&gt;

&lt;h2&gt;
  
  
  An alternative to SQL
&lt;/h2&gt;

&lt;p&gt;Let's understand first what a database does. A database can achieve two main functions: &lt;strong&gt;perform calculations and process transactions&lt;/strong&gt;, which are what we often call OLAP and OLTP. When it comes to databases, we want systems that &lt;strong&gt;run fast and make interacting with the databases (writing queries) easy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever thought about SQL's limitations when it comes to these two characteristics?&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL Limitation 1: Easiness of writing/reading queries
&lt;/h2&gt;

&lt;p&gt;Let’s start with easy in writing.&lt;/p&gt;

&lt;p&gt;When solving real life problems (not textbook problems), SQL statements can be ugly very quickly. Here's a relatively simple example, to calculate the maximum number of consecutive days that a stock price keeps rising:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select max (consecutive_day)
from (select count(*) (consecutive_day
      from (select sum(rise_mark) over(order by trade_date) days_no_gain
            from (select trade_date,
                         case when closing_price&amp;gt;lag(closing_price) over(order by trade_date)
                              then 0 else 1 END rise_mark
                  from stock_price ) )
      group by days_no_gain)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If writing this sort of queries is not easy, but reading them (whether you or a colleague wrote them) is not easy either.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL Limitation 2: Speed
&lt;/h2&gt;

&lt;p&gt;Let's consider a simple task, often used as an example: take the top 10 items in a dataset containing 100 million pieces of data. This task is not complicated to write in SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT TOP 10 x FROM T ORDER BY x DESC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the execution logic corresponding to this statement is to perform the big sorting for all the data first, and then take the top 10, and discard the remaining data. As we all know that sorting is a very slow action, and will traverse the data many times. If the amount of data is too large to be loaded into memory, it also needs to buffer the data in external storage, resulting in a further sharp decrease in performance. If the logic embodied in this statement is strictly followed, the operation will not run fast anyway. Fortunately, many programmers know that this operation does not need the big sorting, nor the external storage to buffer since it can be done by traversing only once and only occupying a little memory space, it means a higher performance algorithm exists. Regrettably, such algorithm can't be implemented in SQL. We can only hope the database optimizer is smart enough to convert this SQL statement to a high-performance algorithm to execute, but the database optimizer may not be reliable when the situation is complicated.&lt;/p&gt;

&lt;p&gt;It seems that SQL is not doing well in both aspects. Although these two examples are not very complicated, SQL does not perform well in either example. In reality, the difficult-to-write and slow running situation abounds in SQL codes with thousands of lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why these limitations?
&lt;/h2&gt;

&lt;p&gt;To answer this question, we need to analyze what exactly the implementation of calculation with program code does.&lt;/p&gt;

&lt;p&gt;Essentially, the process of programming is &lt;strong&gt;the process of translating problem-solving idea into a precise formal language executable by the computer&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;For the formal language used to describe calculation method, its core lies in the algebraic system adopted. To put it simply, the so-called algebraic system includes two key elements: data types and corresponding operation rules. For instance, the key elements of arithmetic we learned in primary school is the integer and the operations including the addition, subtraction, multiplication and division. Once we get both key elements, we can write the operation we want with the symbols stipulated in the algebraic system to something, i.e., the code, and then the computer can execute. &lt;/p&gt;

&lt;p&gt;At present, the mainstream database is the relational database, and the reason why it is called this way is because its mathematical basis is called &lt;strong&gt;relational algebra&lt;/strong&gt;. SQL is exactly a formal language developed from the theory of relational algebra.&lt;/p&gt;

&lt;p&gt;Now we can answer why SQL is not competent in both aspects we expect. &lt;strong&gt;The problem lies in relational algebra&lt;/strong&gt;, and the relational algebra is just like an arithmetic system with only addition and no multiplication. Therefore, it is inevitable that many things cannot be done well.&lt;/p&gt;

&lt;p&gt;And, unfortunately, this problem is at the theoretical level, and it won't help no matter how optimized it is in practice, it can only be improved in a limited way, not eradicated. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why SPL is competent
&lt;/h2&gt;

&lt;p&gt;SPL's theoretical basis is no longer the relational algebra, but something called &lt;strong&gt;discrete dataset&lt;/strong&gt;. The formal language designed based on this new algebra is named &lt;strong&gt;SPL&lt;/strong&gt; (structured process language).&lt;/p&gt;

&lt;p&gt;SPL redefines and extends many operations of structured data, specifically, it adds the discreteness, enhances ordered computation, implements a thorough set orientation, supports object references, and advocates stepwise operation.&lt;/p&gt;

&lt;p&gt;Recoding the previous problems in SPL will give you a direct feeling. To calculate the maximum consecutive days that a stock keeps rising:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stock_price.sort(trade_date).group@i(closing_price&amp;lt;closing_price[-1]).max(~.len())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the calculation idea is the same as the previous SQL, it is easier to express and no longer confusing, because of the introduction of ordering characteristic.&lt;/p&gt;

&lt;p&gt;Take the top 10 out of 100 million pieces of data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T.groups(;top(-10,x))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SPL has richer set data types, it is easy to describe the efficient algorithm that implements simple aggregation on a single traversal, without involving big sorting action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In addition to theoretical differences, SPL has many engineering-level advantages such as: easier to write parallel computing code, large memory pre-association to improve foreign key join performance, unique column storage mechanism to support arbitrary segmentation and parallel computing, etc.&lt;/p&gt;

&lt;p&gt;For more details, check out their &lt;a href="https://github.com/SPLWare/esProc"&gt;Github repo&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Merkle Trees and Bitcoin</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Mon, 08 Feb 2021 19:22:35 +0000</pubDate>
      <link>https://dev.to/codinglanguages/merkle-trees-and-bitcoin-k36</link>
      <guid>https://dev.to/codinglanguages/merkle-trees-and-bitcoin-k36</guid>
      <description>&lt;p&gt;This post was originally published at &lt;a href="https://www.yourdevopsguy.com/merkle-trees-and-bitcoin/"&gt;https://www.yourdevopsguy.com/merkle-trees-and-bitcoin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Merkle trees, also known as &lt;em&gt;binary hash trees&lt;/em&gt;, are a type of &lt;a href="https://www.yourdevopsguy.com/recursion-vs-iteration-13-ways-to-traverse-a-tree/"&gt;binary tree&lt;/a&gt;. They can be used to &lt;strong&gt;efficiently verify the integrity of large sets of data&lt;/strong&gt;. They are used in both blockchain and non-blockchain-related projects.&lt;/p&gt;

&lt;p&gt;Merkle trees are build from the bottom up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The leaves of the tree contain the hash of each element in our dataset. This dataset could represent a list of transactions, parts of a file, etc.&lt;/li&gt;
&lt;li&gt;Each internal node is the result of &lt;strong&gt;hashing&lt;/strong&gt; the concatenation of the hashes of its two children.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5-URJdDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/tree-1-1024x576.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5-URJdDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/tree-1-1024x576.jpg" alt="img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hash functions&lt;/li&gt;
&lt;li&gt;Properties of a Merkle tree&lt;/li&gt;
&lt;li&gt;What problems can a Merkle tree solve?&lt;/li&gt;
&lt;li&gt;Implementing a Merkle tree in JavaScript&lt;/li&gt;
&lt;li&gt;Known vulnerability&lt;/li&gt;
&lt;li&gt;Sparse Merkle Trees&lt;/li&gt;
&lt;li&gt;Conclusions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://en.wikipedia.org/wiki/Hash_function#:~:text=A%20hash%20function%20is%20any,%2C%20digests%2C%20or%20simply%20hashes."&gt;&lt;strong&gt;Hash functions&lt;/strong&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Hash functions take as input any piece of data (a string, an image, etc.) and produce a fixed-length output. An example of a hash function is SHA-256, which takes data of arbitrary size and produces an output that is 256 bits long.&lt;/p&gt;

&lt;p&gt;Good hash functions have the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Uniformity&lt;/strong&gt;. They produce evenly distributed outputs in the possible output range. In the SHA-256 example, this range would go from 0000...0000 to 1111...1111.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt;. The same input will always generate the same output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast to compute&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function"&gt;Cryptographic hash functions&lt;/a&gt; need additional properties to make them more secure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-way functions&lt;/strong&gt;. Given an input x, they generate an output h(x). From an output h(x), it is computationally infeasible to find the input it came from, x.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collision resistant&lt;/strong&gt;. The likelihood of 2 different inputs x, y producing the same output h(x)=h(y) should be negligible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resistant to preimage attacks&lt;/strong&gt;. Given an output h(x), it is infeasible to find an input y such as h(x) = h(y).&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;minor modification in the input&lt;/strong&gt; will produce a &lt;strong&gt;completely different output&lt;/strong&gt;. This is known as the &lt;a href="https://en.wikipedia.org/wiki/Avalanche_effect"&gt;avalanche effect&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Properties of a Merkle Tree&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The properties of a Merkle tree derive from its structure and its use of hash functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data integrity&lt;/strong&gt;. The root of the tree will change if any node in the tree is modified. Even the same dataset, with its elements presented in a different order (ex: [T2, T1, T3, T4] instead of [T1, T2, T3, T4]) will produce a different tree.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial verification&lt;/strong&gt;. We do not need the full tree to verify whether a transaction belongs to it. We only need a path that starts in one of the leaves and goes all the way up to the root (proof of inclusion).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The height of a tree of N leaves is&lt;/strong&gt; ceil(log2(N)). The function ceil(x), known as &lt;em&gt;ceil&lt;/em&gt;, maps x to the smallest integer greater or equal than x. Ex: ceil(3.14) = 4 and ceil(3) = 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What problems can a Merkle tree solve?&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction to Blockchain
&lt;/h3&gt;

&lt;p&gt;I will use &lt;strong&gt;Bitcoin&lt;/strong&gt; to illustrate how Merkle trees can verify if a transaction belongs to a block. In case you aren’t familiar with blockchains, we can oversimplify things imagining that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A blockchain is a &lt;strong&gt;distributed linked list&lt;/strong&gt; of elements called &lt;strong&gt;blocks&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Blocks contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A list of &lt;strong&gt;transactions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A header that stores metadata.&lt;/li&gt;
&lt;li&gt;Part of this metadata is the root of the block’s Merkle tree, called &lt;strong&gt;Merkle root&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Each block points to the hash of its predecessor&lt;/strong&gt;, to ensure immutability. If the previous block in the chain changes, even by one bit, its hash would change and it would break the chain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine you are running an app that needs to verify if a transaction &lt;strong&gt;T&lt;/strong&gt; belongs to a block &lt;strong&gt;B&lt;/strong&gt;. In Bitcoin, &lt;a href="https://bitcoin.org/en/full-node"&gt;full nodes&lt;/a&gt; store a block’s Merkle root along with all its transactions. For them, it is easy to verify if &lt;strong&gt;T&lt;/strong&gt; belongs to &lt;strong&gt;B&lt;/strong&gt;. Also, they can generate proofs for any transaction in a block on demand.&lt;/p&gt;

&lt;p&gt;What if the app runs on a device with limited disk, computing power, and bandwidth? To determine whether &lt;strong&gt;T&lt;/strong&gt; belongs to &lt;strong&gt;B&lt;/strong&gt;, the device needs information. It can retrieve this information from other participants in the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problems
&lt;/h3&gt;

&lt;p&gt;The following problems arise:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How can we &lt;strong&gt;trust that the data we receive from other nodes is correct&lt;/strong&gt;? Data might be corrupted and other nodes in the network can send fake data.&lt;/li&gt;
&lt;li&gt;Given the limited resources, how can we &lt;strong&gt;minimize the amount of information we need to receive from the network&lt;/strong&gt;?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Merkle trees can help to solve these problems. From the properties of Merkle trees we covered above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data integrity&lt;/strong&gt; solves problem 1. Let’s assume we receive different pieces of information from a series of participants in the network. We have &lt;strong&gt;B&lt;/strong&gt;, which contains its Merkle root. The data we receive from the network is used to build a Merkle tree whose root must be the same as &lt;strong&gt;B&lt;/strong&gt;‘s Merkle root. Otherwise, we cannot trust the data that others have shared with us.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial verification&lt;/strong&gt; and having a &lt;strong&gt;height of&lt;/strong&gt; ceil(log2(N)) solve problem 2. Hashing all the transactions would also work to verify data integrity. However, that does not scale well, because proof generation and verification would be O(N) operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Simplified Payment Verification(SPV) nodes,&lt;/strong&gt; commonly known as &lt;a href="https://en.bitcoin.it/wiki/Lightweight_node"&gt;lightweight nodes or light clients&lt;/a&gt;, do not store full blocks. They interact with the network to request the information they need to verify transactions. They can assess whether a transaction belongs to a block requesting an &lt;strong&gt;inclusion proof&lt;/strong&gt; and the block header, where the &lt;strong&gt;Merkle root&lt;/strong&gt; is stored.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Implementing a Merkle Tree in JavaScript&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The algorithm to generate a Merkle root from a list of transactions is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gxMcnzwF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/big-tree-compressed-1024x576.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gxMcnzwF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/big-tree-compressed-1024x576.jpg" alt="img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The leaves of a Merkle tree contain the hashes of the transactions that belong to a block. In the image above, [T1, T2, T3, T4, T5, T6] represent transactions.&lt;/li&gt;
&lt;li&gt;From them, we generate the leaves of the Merkle tree using a hash function. If the number of transactions is odd, we duplicate the last node.&lt;/li&gt;
&lt;li&gt;We take 2 consecutive leaves and hash the concatenation of their hashes. This generates their parent. In the image, T1’s and T2’s parent is equal to hash(hash(T1) + hash(T2)).&lt;/li&gt;
&lt;li&gt;We keep repeating this process with all the transactions at the same “level”. These parents will be siblings that will form a new level in the tree hierarchy.&lt;/li&gt;
&lt;li&gt;We keep repeating this process until we only have one element left, the root of the tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find &lt;a href="https://github.com/serfuenav/merkleTree"&gt;here&lt;/a&gt; my implementation of a Merkle tree. It can verify a Bitcoin block’s Merkle root and generate and verify proofs of inclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Known vulnerability&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Bitcoin’s Merkle tree duplicates the last node in levels with an odd number of nodes. Also, if Bitcoin finds a block that is not valid, it caches its root to avoid trying to mine it again. This combination makes the tree susceptible to &lt;a href="https://en.wikipedia.org/wiki/Preimage_attack"&gt;second preimage attacks&lt;/a&gt;: for an input x, we can find a second input y, different from x, such that h(x) = h(y).&lt;/p&gt;

&lt;p&gt;How does this design suffer from this? Let’s go back to our first example, based on the tree represented on the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gxMcnzwF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/big-tree-compressed-1024x576.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gxMcnzwF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.yourdevopsguy.com/wp-content/uploads/2021/01/big-tree-compressed-1024x576.jpg" alt="img"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The leaves of the tree come from a block &lt;strong&gt;B1&lt;/strong&gt; containing these transactions [T1, T2, T3, T4, T5, T6]&lt;/li&gt;
&lt;li&gt;The level right above the leaves is [hash(hash(T1) + hash(T2)), hash(hash(T3) + hash(T4)), hash(hash(T5) + hash(T6))]&lt;/li&gt;
&lt;li&gt;Since we have an odd number of nodes, we duplicate the last one. Hence, the next level changes to [..., ..., hash(hash(T5) + hash(T6)), hash(hash(T5) + hash(T6))]&lt;/li&gt;
&lt;li&gt;This is equal to the level produced by a block &lt;strong&gt;B2&lt;/strong&gt; with the following transactions [T1, T2, T3, T4, T5, T6, T5, T6].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;B2&lt;/strong&gt; contains duplicate transactions, making the block invalid. Nodes would cache this root so that next time they find &lt;strong&gt;a block with this root&lt;/strong&gt; they discard it. Both B1 and B2 produce the same root. Thus, nodes will reject &lt;strong&gt;B1&lt;/strong&gt;, even though B1 might be a valid block.&lt;/p&gt;

&lt;p&gt;For more details, have a look at &lt;a href="https://bitcointalk.org/index.php?topic=102395.0"&gt;this post&lt;/a&gt; and&lt;a href="https://github.com/bitcoin/bitcoin/blob/c7ad94428ab6f54661d7a5441e1fdd0ebf034903/src/consensus/merkle.cpp#L8"&gt; this comment&lt;/a&gt; in Bitcoin’s source code.&lt;/p&gt;

&lt;p&gt;There is another known vulnerability in Bitcoin’s original Merkle trees (already fixed). Understanding it requires more knowledge of how Bitcoin builds transactions. Since this is an introductory article, I have decided to leave it out. However, I might cover transactions in more depth in future articles and revisit this vulnerability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sparse Merkle Trees
&lt;/h2&gt;

&lt;p&gt;A Sparse Merkle Tree (SMT) is a variation of a Merkle Tree, where every leaf node has an index along with its value. All leaves are initialized to an empty (null) value. By design, SMTs have 2^256 leaves.&lt;/p&gt;

&lt;p&gt;The Merkle tree I described above can verify that a transaction is part of the block by exploring the path from its corresponding leaf to the root of the tree.&lt;/p&gt;

&lt;p&gt;However, they cannot be used to prove that a transaction does not belong to a block. And in general, to prove that elements do not belong to a dataset. SMTs can do this.&lt;/p&gt;

&lt;p&gt;SMTs can produce proofs of non-inclusions in an efficient manner. The idea is that we know the index of every element. Thus, you know which leaf contains an element. If an element is not part of the tree, the leaf where the element would be stored will be null. Therefore, to produce a proof of non-inclusion, we produce a proof of inclusion generated from that node initialized to null.&lt;/p&gt;

&lt;p&gt;Proofs of inclusion work in the same way as Merkle trees’.&lt;/p&gt;

&lt;p&gt;Updating a leaf an SMT is also efficient because we only need to modify the path that goes from that leaf to the root. Since SMTs have 2^256 leaves, only 256 nodes need modification.&lt;/p&gt;

&lt;p&gt;SMTs deserve their own article, but I wanted to at least introduce the basic idea behind them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Now you should have a clearer idea of what Merkle trees are and what they are used for. If you want to learn more, I suggest you investigate how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git uses them to keep track of changes in files.&lt;/li&gt;
&lt;li&gt;DynamoDB uses them to identify any inconsistencies between nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you found this article helpful. Share it, because you could help someone pass their exams or get a job.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>algorithms</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>6 Hard Dynamic Programming Problems Made Easy</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Tue, 19 Jan 2021 12:54:41 +0000</pubDate>
      <link>https://dev.to/codinglanguages/6-hard-dynamic-programming-problems-made-easy-2ff0</link>
      <guid>https://dev.to/codinglanguages/6-hard-dynamic-programming-problems-made-easy-2ff0</guid>
      <description>&lt;p&gt;In this &lt;a href="https://www.yourdevopsguy.com/all-you-need-to-know-about-dynamic-programming/"&gt;article&lt;/a&gt;, I gave you an introduction to Dynamic Programming with several examples. Here I will solve 6 harder Dynamic Programming problems to show you how to approach them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/unique-paths/"&gt;Unique Paths&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A robot is located at the top-left corner of a &lt;code&gt;m x n&lt;/code&gt; grid&lt;/p&gt;

&lt;p&gt;The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid.&lt;/p&gt;

&lt;p&gt;How many possible unique paths are there?&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Given that the robot can only move to the right or down, we can reach the position {m,n} (bottom-right corner) in two different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Going to the right from (m, n -1)&lt;/li&gt;
&lt;li&gt;Going down from (m -1, n)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, the total number of paths to (m, n) will be the number of paths to (m, n-1) plus the number of paths to (m-1, n). These two new problems are just instances of the original problem. Therefore we can use recursion to generate a solution.&lt;/p&gt;

&lt;p&gt;Let's call f(m,n) the number of ways to reach the position (m, n).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;outside&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Recursive solution
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Line 5 represents the number of paths to reach any position in the first column or row of the grid (we can only reach them by going all the way right or down, therefore we return 1).&lt;/p&gt;

&lt;p&gt;We can improve upon this if we notice that many problems will be computed more than once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To compute f(m,n) we need f(m-1, n) and f(m, n-1).&lt;/li&gt;
&lt;li&gt;For f(m-1, n) we need f(m-2, n) and &lt;strong&gt;f(m-1, n-1)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;For f(m, n-1) we need f(m, n-2) and &lt;strong&gt;f(m-1, n-1)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you suspect a problem might be solved via Dynamic Programming problems, &lt;strong&gt;I recommend drawing a tree with all possible paths to see if there are repeated subproblems. &lt;/strong&gt;If you can derive a recursion and prove that there are repeated subproblems and optimal substructure, you can apply Dynamic Programming.&lt;/p&gt;

&lt;h4&gt;
  
  
  Top-down Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;Going from the recursive solution to a top-down DP solution is very straightforward. We just need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the results are already in our cache. If so, we return them.&lt;/li&gt;
&lt;li&gt;If they're not, cache them before we return.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In line 8, I check &lt;code&gt;if (-1 == dp[n])&lt;/code&gt; to avoid bugs like &lt;code&gt;if(dp[n] = -1)&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bottoum-up Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;Now, let's take a different look at the problem. From (0,0) we can go right to (0,1), (0,2), etc. There is only one way to reach these positions. Similarly, there is only one way to reach all the positions in the first column: going down from (0,0). We can start building a table with this information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// Empty grid&lt;/span&gt;
&lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="c1"&gt;// first row&lt;/span&gt;
&lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="c1"&gt;// first col&lt;/span&gt;
&lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Any other position follows the same logic as in the top-down approach&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This approach will build the full m*n table with all possible results. We return the one we are interested in: the most bottom-right position.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Complexity
&lt;/h3&gt;

&lt;p&gt;Computing the complexity of the bottom-up approach is trivial. There are two nested loops in which the amount of work is constant, giving an overall time complexity of O(&lt;em&gt;mn&lt;/em&gt;). The space complexity is O(m*n*) as well.&lt;/p&gt;

&lt;p&gt;For the top-down, it seems a bit trickier, but the logic is the same. We do constant work for every call (because we cache results) and there are O(mn) calls. Therefore, the time complexity is O(&lt;em&gt;mn&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This problem can be solved in O(m+n) using basic mathematics. You have m rows, n columns and you can only move to the right and down (states). You can code a path using R to symbolize right and D for down. Then, for m rows and n columns you need to generate a string of (m-1) + (n-1) elements that have 2 states: R or D. In this string, there will be m-1 Ds and n-1 Rs. This problem is equivalent to find all permutations of an array of m+n-2 elements (taking into account all the repetitions):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/unique-paths-ii/"&gt;Unique Paths 2&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A robot is located at the top-left corner of a &lt;code&gt;m x n&lt;/code&gt; grid (marked 'Start' in the diagram below).&lt;/p&gt;

&lt;p&gt;The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid.&lt;/p&gt;

&lt;p&gt;Now consider if some obstacles are added to the grids. How many unique paths would there be?&lt;/p&gt;

&lt;p&gt;An obstacle and space is marked as &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt; respectively in the grid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Try to solve this one without looking at my solution. The code (for any of the approaches I described for the previous problem) is almost the same. You only need to take into account that cells have values and some of them can be blocked. If a cell is blocked, the robot cannot visit it and therefore there are 0 ways in which the robot can reach, from a cell where the is an obstacle, the cell to its right or down.&lt;/p&gt;

&lt;p&gt;To avoid duplication, here is the code only for the bottom-up approach.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/coin-change/"&gt;Coin Change&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You are given coins of different denominations and a total amount of money &lt;em&gt;amount&lt;/em&gt;. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return &lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You may assume that you have an infinite number of each kind of coin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Recursive solution
&lt;/h4&gt;

&lt;p&gt;Imagine you need to solve this problem by hand. At every step, you have an &lt;em&gt;amount&lt;/em&gt; of money and a few coins to choose from. Let's say the coins are 1,2 and 5, and the amount is 11. You can take three different paths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Take the coin with value 1. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;10&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; Choose the coin with value 2. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;9&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; Take the coin with value 5. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;6&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Which one will produce the desired output (minimum number of coins)? At this stage, we don't know. We need to explore each path in full and return the minimum.&lt;/p&gt;

&lt;p&gt;It is pretty obvious now that we can use recursion to solve this. It should look something like this, with f(n) representing the minimum number of coins to reach n&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// No solution&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;coins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In C++:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h4&gt;
  
  
  Top-down Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;From this it is trivial to get a top-down solution. You only need to add a cache, as we did in the previous problem:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Bottom-up Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;The bottom-up solution takes a different path. The idea is to fill a table with the minimum amount of coins needed to generate the values [0, amount], starting from the "initial conditions":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;f(0) = 0&lt;/li&gt;
&lt;li&gt;From 0, we can use one coin to get to all the values in the array &lt;em&gt;coins&lt;/em&gt;. We initialize them to 1.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may have noticed that I have created arrays that seem to have an extra element. The entry sol[0] represents the problem of reaching the amount 0. This is why it seems there is an offset of 1 in the code (we return sol[amount] instead of sol[amount -- 1] because indices represent quantities). You will see this pattern in more places in this article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How would you solve this problem if there there wasn't an infinite number of each kind of coin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="//https//leetcode.com/problems/coin-change-2/"&gt;Coin Change 2&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount.&lt;/p&gt;

&lt;p&gt;You may assume that you have infinite number of each kind of coin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Let's review our previous example: amount = 11 and coins = [1,2,5]. Again, we have the same three choices.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Take the coin with value 1. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;10&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; Choose the coin with value 2. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;9&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; Take the coin with value 5. You're facing now with the problem of computing the fewest number of coins that you need to get to &lt;em&gt;6&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, instead of getting the minimum of the three, we return the sum of the three paths. If we arrive to an instance where amount = 0, we return 1 (it is a solution we need to count). If amount is negative, that path doesn't lead to a solution and we return 0.&lt;/p&gt;

&lt;p&gt;Since this is just a variation on the previous problem, I will only write the C++ implementation of the bottom-up approach. You have the tools to generate recursive and top-down solutions.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/edit-distance/"&gt;Edit Distance&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given two strings &lt;code&gt;word1&lt;/code&gt; and &lt;code&gt;word2&lt;/code&gt;, return &lt;em&gt;the minimum number of operations required to convert &lt;code&gt;word1&lt;/code&gt; to &lt;code&gt;word2&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You have the following three operations permitted on a word:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert a character&lt;/li&gt;
&lt;li&gt;Delete a character&lt;/li&gt;
&lt;li&gt;Replace a character&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: word1 = "horse", word2 = "ros"&lt;/li&gt;
&lt;li&gt;Output: 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Recursive solution
&lt;/h4&gt;

&lt;p&gt;This problem seems tricky at first, so we need to be systematic and try to work our way into a solution from a good example. Let's take "horse" and "ros", and focus on the last character of each word:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If "e" and "s" were the same, we could "forget about them" and keep working with "hors" and "ro"&lt;/li&gt;
&lt;li&gt;Since "e" and "s" are different, we need to make them equal. We have 3 choices:

&lt;ul&gt;
&lt;li&gt;Replace "e" with "s" (or "s" with "e"), and now they're the same&lt;/li&gt;
&lt;li&gt;Delete "e" (or "s") and see and continue with the rest of the string "hors" and "ros" to see&lt;/li&gt;
&lt;li&gt;Insert a character ("s" or "e" respectively) to make the last characters equal&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each possibility will generate another subproblem of smaller size, therefore we can code this recursively. We need to find the minimum of these 3 branches and return it (plus 1, since taking any of these paths indicates that there is at least one &lt;em&gt;edit operation&lt;/em&gt;).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Top-down Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;If you play around with this example you'll see that this problem has optimal substructure, so I'll just show you the code for the solution top-down here:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Bottom-up Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;And bottom-up here:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/word-break/"&gt;Word Break&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given a &lt;strong&gt;non-empty&lt;/strong&gt; string &lt;em&gt;s&lt;/em&gt; and a dictionary &lt;em&gt;wordDict&lt;/em&gt; containing a list of &lt;strong&gt;non-empty&lt;/strong&gt; words, determine if &lt;em&gt;s&lt;/em&gt; can be segmented into a space-separated sequence of one or more dictionary words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same word in the dictionary may be reused multiple times in the segmentation.&lt;/li&gt;
&lt;li&gt;You may assume the dictionary does not contain duplicate words.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: s = "leetcode", wordDict = ["leet", "code"]&lt;/li&gt;
&lt;li&gt;Output: true&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Recursive solution
&lt;/h4&gt;

&lt;p&gt;This problem has a relatively straightforward solution. If we were to solve this by hand, we would start taking prefixes of our input and see if they belong to our dictionary. As soon as we find one, we repeat the process with the remaining of the string. In other words, we solve a smaller instance of the same problem. Let's try to define the recursion first and later see if there are overlapping subproblems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// if the string is empty, it can be decomposed using the words in wordDict\&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;every&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;correspondent&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's use the following example to illustrate this algorithm:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;dogsandcats&lt;/span&gt;
&lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt; We start taking prefixes of s until we find one that belongs to dict. In this case, the first prefix that meets this condition is &lt;em&gt;dog&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; Our new string s' is "andcats". Repeating 1 we get to sand.&lt;/li&gt;
&lt;li&gt; Now, s" is "cats". The prefix cats belongs to the dictionary.&lt;/li&gt;
&lt;li&gt; Since s"' is empty, we return true.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This snippet of code solves this problem recursively:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h4&gt;
  
  
  Top-down Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;Coming back to the example, you can see that bot "dogs" + "and" and "dog" + "sand" produce the same suffix: "cat". There are overlapping subproblems and we can use &lt;em&gt;memoization&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Bottom-up Dynamic Programming
&lt;/h4&gt;

&lt;p&gt;The bottom-up approach builds a table, where the empty string is initialized to true and every other entry to false. From there, the logic is the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We build the solution for all the substrings of s, from length 0 to the length of s. This is why we have a loop in the range &lt;a href="https://dev.toboth%20inclusive,%20since%20they%20represent%20the%20number%20of%20characters%20we're%20considering%20at%20each%20step"&gt;1,n&lt;/a&gt; and another internal loop in the range [i-1,0] to move around all prefixes for that length&lt;/li&gt;
&lt;li&gt;If the problem has a solution for the prefix s&lt;a href="https://dev.tothis%20is%20represented%20by%20dp%5Bj%5D"&gt;0,j&lt;/a&gt;, we "follow the recursion" on the suffix s[j+1,:): if this is a valid word, there is a solution for the problem represented by dp[i]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is harder to explain in words than in code, so here it is:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;As we have seen, dynamic programming problems can be solved in a systematic way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Start with small examples and see if their solution can be derived from smaller instances of the same problem. If so, recursion is a natural choice.&lt;/li&gt;
&lt;li&gt; Draw a tree with the possible paths you can take depending on the available choices. If you reach the same parameters more than once, you can improve your solution using a cache.&lt;/li&gt;
&lt;li&gt; From the recursion, arriving at a top-down solution is mechanical: you just need to add a cache.&lt;/li&gt;
&lt;li&gt; The bottom-up approach generates a table based on "the initial conditions" for the recursion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope you found this article helpful. I recommend sharing it with a friend or the rest of the community because you could help someone pass their exams or their next job interview.&lt;/p&gt;

&lt;p&gt;For more content, visit &lt;a href="https://www.yourdevopsguy.com"&gt;my blog&lt;/a&gt;, and connect with me on &lt;a href="https://twitter.com/codinglanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>codenewbie</category>
      <category>algorithms</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Recursion vs Iteration: 13 Ways to Traverse a Tree.</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Fri, 16 Oct 2020 06:06:13 +0000</pubDate>
      <link>https://dev.to/codinglanguages/recursion-vs-iteration-13-ways-to-traverse-a-tree-2n89</link>
      <guid>https://dev.to/codinglanguages/recursion-vs-iteration-13-ways-to-traverse-a-tree-2n89</guid>
      <description>&lt;p&gt;&lt;strong&gt;To understand recursion, you must understand recursion&lt;/strong&gt;. I will show you 13 different ways to traverse a tree to compare recursive and iterative implementations. This way, we will kill two birds with one stone: &lt;strong&gt;recursion and &lt;a href="https://www.yourdevopsguy.com/how-to-learn-data-structures-and-algorithms-20-problem-solving-techniques-you-must-know/" rel="noopener noreferrer"&gt;data structures and algorithms&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Bad programmers worry about the code. Good programmers worry about data structures and their relationships.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Linus_Torvalds" rel="noopener noreferrer"&gt;Linus &lt;/a&gt;&lt;a href="https://en.wikipedia.org/wiki/Linus_Torvalds" rel="noopener noreferrer"&gt;Torvalds&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recursion, iteration and how to traverse a tree are useful skills to have and common in interview questions. &lt;strong&gt;Do not risk failing your next job interview because you didn't take the time to read one article&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I assume you have &lt;strong&gt;basic coding skills&lt;/strong&gt; and are familiar with stacks, queues, recursion, and loops. If this seems too advanced for you, check &lt;a href="https://www.yourdevopsguy.com/how-to-ace-coding-interviews-the-ultimate-guide/" rel="noopener noreferrer"&gt;this article&lt;/a&gt; where I have listed some resources to get you started.&lt;/p&gt;

&lt;p&gt;For every problem, I will provide also a link to Leetcode so that you can play around with my solution or write your own in your preferred programming language.&lt;/p&gt;

&lt;p&gt;My code examples will be in C++. If you are not familiar with the APIs or syntax, that is fine. I am sure you will understand the ideas. That is the goal of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Tree?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fn-tree-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fn-tree-1.png" alt="N-ary tree"&gt;&lt;/a&gt;N-ary tree&lt;/p&gt;

&lt;p&gt;Trees are data structures that organize data hierarchically. They are defined &lt;strong&gt;recursively&lt;/strong&gt; from a &lt;strong&gt;root node&lt;/strong&gt;, that contains the &lt;strong&gt;data&lt;/strong&gt; that needs to be stored and &lt;strong&gt;pointers to its children&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are many types of trees well-suited for specific applications: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Binary_search_tree" rel="noopener noreferrer"&gt;Binary search trees&lt;/a&gt;, for efficient searches on sorted data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/B-tree" rel="noopener noreferrer"&gt;B-trees&lt;/a&gt; to store database indexes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Heap_(data_structure)" rel="noopener noreferrer"&gt;Heaps&lt;/a&gt; to implement &lt;a href="https://en.wikipedia.org/wiki/Priority_queue" rel="noopener noreferrer"&gt;priority queues&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;General trees to implement &lt;a href="https://en.wikipedia.org/wiki/File_system" rel="noopener noreferrer"&gt;filesystems&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There is no point in storing information if you do not know how to access it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For simplicity, I will focus on binary trees. You will take the code and generalize to trees with up to N children per node.&lt;/p&gt;

&lt;p&gt;I will present you with 13 ways to traverse a tree and discuss them in detail. As usual, there will be challenges for you to cement your knowledge. I strongly recommend solving each problem on your own before reading my solution. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are going to learn infinitely more by doing than by reading or watching.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13 Ways To Traverse a Tree
&lt;/h2&gt;

&lt;p&gt;Most of the problems in this section will be on binary trees. We will define a node as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;TreeNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;TreeNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TreeNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TreeNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a &lt;code&gt;struct&lt;/code&gt; makes the fields public by default, which is enough for our purposes.&lt;/p&gt;

&lt;p&gt;For the complexity analysis, we will assume that we will traverse a tree of height &lt;strong&gt;H&lt;/strong&gt; that contains &lt;strong&gt;N&lt;/strong&gt; nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Pre-order Traversal - Recursive
&lt;/h3&gt;

&lt;p&gt;Given the root of a binary tree, return &lt;em&gt;the preorder traversal of its nodes' values&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpre-order.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpre-order.png" alt="Preorder traversal"&gt;&lt;/a&gt;Pre-order traversal&lt;/p&gt;

&lt;p&gt;You can play around with this problem &lt;a href="https://leetcode.com/problems/binary-tree-preorder-traversal" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The pre-order, in-order, and post-order traversal of a tree are defined by the order in which we visit the root, left, and right children of a tree. The pre in pre-order refers to the root. In a preorder traversal of a tree, we first visit the root node, then the left node, and finally the right node. &lt;/p&gt;

&lt;p&gt;You can translate this into recursive code very easily. Your function will receive a node, starting with the root of the tree. You need to define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Base condition&lt;/strong&gt;: As long as the node is not null,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursive relationship&lt;/strong&gt;: you process it (for instance, print its value), and then call the same function in the left and right children.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the base condition, you have two alternatives. I have called them A and B in my code. Have a look at the code and try to figure out the pros and cons of each before you look at my comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;preorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// helperB(root, sol);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Alternatives
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option A&lt;/strong&gt;. Every function call will test whether the node it receives is null or not. Then, it will trigger two recursive calls. This option will result in a larger stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option B&lt;/strong&gt;. The function assumes that the node is not null. It will generate a recursive call only if the left/right child is not null. The function will execute more if statements but make less recursive calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There is no right or wrong solution here without more context&lt;/strong&gt;. In an interview setting, discuss both options. It will show that you care about your code and think of the implications of what you write.&lt;/p&gt;

&lt;p&gt;Your priority should be writing readable and maintainable working code. Only &lt;strong&gt;focus on this level of detail when you have profiled your code&lt;/strong&gt; and have proof that these lines of code make a big impact on the overall performance. Don't guess. Remember.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Premature optimization is the root of all evil."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Donald_Knuth" rel="noopener noreferrer"&gt;Donald Knuth&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;This algorithm visits every node once and adds an element to the end of a vector, which is constant work - &lt;a href="https://en.wikipedia.org/wiki/Amortized_analysis#:~:text=In%20computer%20science%2C%20amortized%20analysis,algorithm%2C%20can%20be%20too%20pessimistic." rel="noopener noreferrer"&gt;amortized&lt;/a&gt;. Therefore, the time complexity is O(N). &lt;/p&gt;

&lt;p&gt;Can you try to figure out the space complexity? Try to visualize the algorithm on the tree above. How many nodes will be stored in the stack in the "worst-case"?&lt;/p&gt;

&lt;p&gt;I am sure you found the correct answer. The maximum number of nodes that you need to store will be equal to the height of the tree, H. Consequently, the space complexity is O(H).&lt;/p&gt;

&lt;p&gt;In the next problem, I will show you a non-recursive implementation of the same algorithm to traverse a tree. But before that, I have a little challenge for you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenge
&lt;/h4&gt;

&lt;p&gt;Given an n-ary tree, return the &lt;em&gt;preorder&lt;/em&gt; traversal of its nodes' values.&lt;/p&gt;

&lt;p&gt;You can code your solution &lt;a href="https://leetcode.com/problems/n-ary-tree-preorder-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  To make you think
&lt;/h5&gt;

&lt;p&gt;A natural follow-up to this problem is to generalize it to trees with N children. Before opening the link to Leetcode, try to first &lt;strong&gt;model the nodes yourself&lt;/strong&gt;. Some interesting questions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What data structures are suitable to store &lt;strong&gt;at most N children&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;If you &lt;strong&gt;don't know the maximum number of children&lt;/strong&gt; a node can have, can you still use this data structure? What other options do you have?&lt;/li&gt;
&lt;li&gt;What if you want to make a generic tree that works for &lt;strong&gt;different data types&lt;/strong&gt;? The answer to this question will depend on your programming language: templates for C++, Generics for Java, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, focus only on the recursive solution. Even if "it is trivial", we have seen that you can still ask questions and discuss different alternatives.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pre-order Traversal - Iterative
&lt;/h3&gt;

&lt;p&gt;Traverse a tree using pre-order traversal. No recursion allowed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpre-order.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpre-order.png" alt="Pre-order traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give it a try &lt;a href="https://leetcode.com/problems/binary-tree-preorder-traversal" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Now we will see that recursion is not the only way to traverse a tree.&lt;/p&gt;

&lt;p&gt;We need to mimic everything that happens under the hood when we use recursive functions. We know that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we visit the root of the tree - add it to the solution.&lt;/li&gt;
&lt;li&gt;Then we process the left child, and finally the right child.&lt;/li&gt;
&lt;li&gt;We will need to create and handle the stack ourselves instead of relying on recursive calls.&lt;/li&gt;
&lt;li&gt;A stack is a Last-In-First-Out data structure. Therefore we have to &lt;strong&gt;push the items in the reverse order we want to extract them&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can turn this description into the following algorithm:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The iterative algorithm begins by adding the root of the tree to a stack &lt;strong&gt;s&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;As long as &lt;strong&gt;s&lt;/strong&gt; is not empty, we &lt;strong&gt;pop&lt;/strong&gt; elements from it. We &lt;strong&gt;add them to the&lt;/strong&gt; data structure that represents the &lt;strong&gt;solution&lt;/strong&gt; because we want to process the parent node before its children.&lt;/li&gt;
&lt;li&gt;We push the children to &lt;strong&gt;s&lt;/strong&gt;. &lt;strong&gt;First the right child and then the left child&lt;/strong&gt;. This way, we will pop the left one before the right one, which is exactly the order in which we want to process them.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;preorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The complexity analysis does not change with respect to the recursive version. We still need to visit the N nodes and do constant work per node. Therefore the time complexity is O(N). &lt;/p&gt;

&lt;p&gt;Regarding the space complexity, the stack will have to store at most a number of nodes proportional to the height of the tree, O(H).&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenge
&lt;/h4&gt;

&lt;p&gt;It is time for you now to generalize this solution to work with a tree of N nodes. You can test your solution &lt;a href="https://leetcode.com/problems/n-ary-tree-preorder-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. In-Order Traversal - Recursive
&lt;/h3&gt;

&lt;p&gt;Given the root of a binary tree, return &lt;em&gt;the inorder traversal of its nodes' values&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fin-order.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fin-order.png" alt="In-order traversal"&gt;&lt;/a&gt;In-order traversal&lt;/p&gt;

&lt;p&gt;Give it a try &lt;a href="https://leetcode.com/problems/binary-tree-inorder-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;In-order traversal is a way to traverse a tree where you first visit the left child, then the root and then the right child. In a binary search tree (like the one above), it will visit the nodes in increasing order.&lt;/p&gt;

&lt;p&gt;The recursive solution is straightforward. The only difference with the pre-order recursive solution is the order in which we visit the root and the children. It is a minor change. Go ahead and implement it yourself.&lt;/p&gt;

&lt;p&gt;Everything we discussed about the extra if statements applies to this problem, as well as the discussion about stack vs RAM. Here is a solution with the same options A and B as before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//helperB(root, sol);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The complexity analysis is the same as the previous recursive example. We are doing exactly the same, just in a different order.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. In-Order Traversal - Iterative
&lt;/h3&gt;

&lt;p&gt;Traverse a tree using &lt;em&gt;in-order&lt;/em&gt; traversal. No recursion allowed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fin-order-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fin-order-1.png" alt="In-order traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test your solution &lt;a href="https://leetcode.com/problems/binary-tree-inorder-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;I know what you are thinking. You are right. We need a stack.&lt;/p&gt;

&lt;p&gt;Let's visualize the in-order traversal of the previous tree. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We call the helper function on the root. &lt;/li&gt;
&lt;li&gt;This calls itself on the left child of the root. &lt;/li&gt;
&lt;li&gt;This calls itself on the left child of the left child of the root. &lt;/li&gt;
&lt;li&gt;This process of moving to the left child repeats until we get to a node &lt;strong&gt;k&lt;/strong&gt; that has no left child. It is only then when we process &lt;strong&gt;k&lt;/strong&gt; that we continue by exploring its right child. &lt;/li&gt;
&lt;li&gt;The implicit stack has stored all the nodes between the root and k. Once we are done with k's right child, the next node to process will be extracted from the implicit stack. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to mimic this with our stack. Let's call it &lt;strong&gt;s&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To kick-off the tree traversal, we add the root of the tree to s.&lt;/li&gt;
&lt;li&gt;If the root does &lt;strong&gt;not&lt;/strong&gt; have a left child or we have finished exploring the root's left subtree, we process the root and move to its right child.&lt;/li&gt;
&lt;li&gt;Otherwise, this is the case where we keep moving left:

&lt;ol&gt;
&lt;li&gt;We add the root to the stack - to process it later&lt;/li&gt;
&lt;li&gt;We move to the left&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;From this algorithm, it looks like we need a &lt;strong&gt;stack and a pointer n&lt;/strong&gt; to mark the node we are currently at. If n becomes null, it means we are done exploring a subtree and need to query the stack for the next node to process. If the stack is empty, we have processed all nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;hasToGoRight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasToGoRight&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The complexity analysis is exactly the same as before: O(N) time complexity and O(H) space complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Post-Order Traversal - Recursive
&lt;/h3&gt;

&lt;p&gt;Given the root of a binary tree, return &lt;em&gt;the postorder traversal of its nodes' values&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpost-order.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpost-order.png" alt="Post-order traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check your implementation &lt;a href="https://leetcode.com/problems/binary-tree-postorder-traversal" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;In a post-order traversal, we first visit the left child, then the last child and finally the root of the tree, hence the name &lt;strong&gt;post&lt;/strong&gt;-order. This algorithm requires a minimal change with respect to the pre-order and in-order traversals that we have just seen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;postorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//helperB(root, sol);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;helperA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helperB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        
        &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;Same as pre-order's and in-order's.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenge
&lt;/h4&gt;

&lt;p&gt;Try to generalize this to work with N nodes. Code your solution &lt;a href="https://leetcode.com/problems/n-ary-tree-postorder-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Post-Order Traversal - Iterative
&lt;/h3&gt;

&lt;p&gt;Traverse a binary tree using &lt;em&gt;post-order&lt;/em&gt; traversal. No recursion allowed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpost-order-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fpost-order-1.png" alt="Postorder traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try your solution &lt;a href="https://leetcode.com/problems/binary-tree-postorder-traversal" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;If you are thinking that we need a stack again, you are right.&lt;/p&gt;

&lt;p&gt;I am familiar with relatively complex solutions based on one stack. This solution can be implemented with two stacks or just one stack and one vector. This can be done with a second stack. The space complexity is still O(N).&lt;/p&gt;

&lt;p&gt;If you remember correctly, for iterative pre-order traversal we added the root to the solution and then pushed the left and right child. I know this comes out of nowhere, but let's see what happens if we first push the left child and then the right child.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;postorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can verify that we obtain [18, 21, 22, 20, 16], which is the same as reversing the pre-order traversal of this tree: [16, 20, 22, 21, 18]. We only need to add an extra step at the end of the algorithm to reverse the solution - or use two stacks.&lt;/p&gt;

&lt;p&gt;I don't have an intuition for this algorithm. I must admit I had to look up this solution on the internet because I did not want to present more complex alternatives.&lt;/p&gt;

&lt;p&gt;Above all, it is worth noting is that &lt;strong&gt;sometimes it is useful to play with similar problems to try to get a solution to the problem you are trying to solve&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;postorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;        
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The complexity is linear both in time and space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time&lt;/strong&gt;: we are doing constant work per element. Reversing a vector is also a linear-time operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Space&lt;/strong&gt;: the space complexity is linear, whether we use one or two stacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Morris Traversal - How to Traverse a Tree Using Constant Space
&lt;/h3&gt;

&lt;p&gt;Traverse a tree using pre-order and in-order traversal. Your space complexity must be O(1) - you cannot use recursion or use any data structures to store information about the nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;You are right. You still need to store some information about the nodes to visit them. This algorithm modifies the nodes to be able to traverse the tree without explicit data structures. At the end of the algorithm, the nodes is back to their original state.&lt;/p&gt;

&lt;p&gt;Let's focus on the in-order traversal. Pre-order just needs a minor modification.&lt;/p&gt;

&lt;p&gt;We will have two pointers: &lt;em&gt;current&lt;/em&gt; and &lt;em&gt;explorer&lt;/em&gt;. We will use &lt;em&gt;explorer&lt;/em&gt; to move around the tree and build links from some leaves back to &lt;em&gt;current&lt;/em&gt;. &lt;strong&gt;Current can only move left if we have previously built a link from its predecessor back to current&lt;/strong&gt;. &lt;strong&gt;This is the only thing I have "memorized" about Morris&lt;/strong&gt;. From this, I can draw a tree and rebuild the algorithm every time.&lt;/p&gt;

&lt;p&gt;This image has all the links that we will need to build. However, we do not need to keep any of them: &lt;strong&gt;as soon as we are done using a bridge, we destroy it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2FMorris-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2FMorris-1.png" alt="Morris traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The algorithm goes as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, we set &lt;em&gt;current&lt;/em&gt; to root.&lt;/li&gt;
&lt;li&gt;If &lt;em&gt;current&lt;/em&gt; &lt;strong&gt;does not&lt;/strong&gt; have a left child, we add &lt;em&gt;current&lt;/em&gt; to the solution and move to its right child.&lt;/li&gt;
&lt;li&gt;Otherwise:

&lt;ol&gt;
&lt;li&gt;We find &lt;em&gt;curren*t's predecessor, using *explorer&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;If there is already a link between &lt;em&gt;explorer&lt;/em&gt; and &lt;em&gt;current&lt;/em&gt;, we break it, add &lt;em&gt;current&lt;/em&gt; to the solution and move to &lt;em&gt;current's&lt;/em&gt; right child.&lt;/li&gt;
&lt;li&gt;Otherwise, we build a link between &lt;em&gt;explorer&lt;/em&gt; and &lt;em&gt;current&lt;/em&gt; and move &lt;em&gt;current&lt;/em&gt; to its left child.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Go back to 2 until &lt;em&gt;*&lt;em&gt;current&lt;/em&gt;&lt;/em&gt;* becomes null.&lt;/li&gt;

&lt;/ol&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's run the algorithm step by step on the tree above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current starts at 7.&lt;/li&gt;
&lt;li&gt;Using explorer, we find its predecessor, 6, and link it back to current.&lt;/li&gt;
&lt;li&gt;We move current to 4.&lt;/li&gt;
&lt;li&gt;Using explorer, we find its predecessor, 4, and link it back to current.&lt;/li&gt;
&lt;li&gt;We move current to 2.&lt;/li&gt;
&lt;li&gt;Current has no left child, so our solution becomes: [2].&lt;/li&gt;
&lt;li&gt;We move to current's right, 4.&lt;/li&gt;
&lt;li&gt;Using explorer, we find its predecessor, 2.&lt;/li&gt;
&lt;li&gt;Since explorer (2) is already linking to current (4), we break this link and add 4 to our solution: [2, 4]&lt;/li&gt;
&lt;li&gt;We move current to its right child, 5.&lt;/li&gt;
&lt;li&gt;Current has no left child, so we add it to our solution [2, 4, 5] and move to its right child&lt;/li&gt;
&lt;li&gt;We are in the same situation as step 9. Our solution becomes [2, 4, 5, 6] and current is back at 7.&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my C++ implementation of this algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inorderTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;explorer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="c1"&gt;//Find currents predecessor&lt;/span&gt;
                &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;explorer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

              &lt;span class="c1"&gt;//Is it linking back to current?&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference between in-order and pre-order is in the last block, where we check if there is an existing link or not. We just need to move around the line in which we add current to the solution.&lt;/p&gt;

&lt;p&gt;For pre-order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Is it linking back to current?&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Morris post-order traversal is a bit trickier, so I will leave it out of this section.&lt;/p&gt;

&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The time complexity is an exercise for you.&lt;/p&gt;

&lt;p&gt;The space complexity is O(1). We are implicitly  using more since we are modifying the tree, but technically we do not need extra space to execute this algorithm.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenge
&lt;/h4&gt;

&lt;p&gt;Can you find some potential issues with this algorithm? For example, if multiple threads had to perform this algorithm on the same tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Level Order Traversal - Iterative
&lt;/h3&gt;

&lt;p&gt;Given a binary tree, return the &lt;em&gt;level order&lt;/em&gt; traversal of its nodes' values. (ie, from left to right, level by level). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Flevel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Flevel.png" alt="Level order traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this tree, the solution looks like: [[15], [10, 21], [5, 20, 23], [6]].&lt;/p&gt;

&lt;p&gt;Try to solve it &lt;a href="https://leetcode.com/problems/binary-tree-level-order-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;This time I will start with the iterative solution because I find it simpler to code. We can solve this problem by applying &lt;a href="https://en.wikipedia.org/wiki/Breadth-first_search" rel="noopener noreferrer"&gt;BFS&lt;/a&gt;. The only trick is how to know when to start a new level. We can do this in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After we push all the nodes in a level, we introduce a special type of node that indicates that we need a new level - for example, a nullptr.&lt;/li&gt;
&lt;li&gt;Before we start processing the queue, we take note of its size s - the elements at that level. We create a new level after we have process &lt;strong&gt;s&lt;/strong&gt; elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here I have taken the second approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;levelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;We visit N nodes and do constant work per node. In other words, the time complexity of this approach is O(N). &lt;/p&gt;

&lt;p&gt;The space complexity is the maximum size of the queue. Since we store elements by level, it is a function of the width of the tree.&lt;/p&gt;

&lt;p&gt;In the case of a &lt;strong&gt;full tree&lt;/strong&gt; (every node has two children except for the leaves) of height H, the maximum number of nodes in a level will occur at the last level (the leaves), being this 2^H. For this type of tree, H = log2(N). &lt;/p&gt;

&lt;p&gt;In conclusion, the space complexity is O(N) too.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenge
&lt;/h4&gt;

&lt;p&gt;Try to solve &lt;a href="https://leetcode.com/problems/print-binary-tree/" rel="noopener noreferrer"&gt;this variant&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Level-order Traversal - Recursive
&lt;/h2&gt;

&lt;p&gt;Given a binary tree, return the &lt;em&gt;level order&lt;/em&gt; traversal of its nodes' values. (ie, from left to right, level by level). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Flevel-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Flevel-1.png" alt="Level order traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this tree, the solution looks like: [[15], [10, 21], [5, 20, 23], [6]].&lt;/p&gt;

&lt;p&gt;Try to solve the problem &lt;a href="https://leetcode.com/problems/binary-tree-level-order-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Always keep in mind the three basic ways to traverse a tree: pre-order, in-order and post-order. This problem is a &lt;strong&gt;pre-order tree traversal in disguise&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The only extra is that you want &lt;strong&gt;to put nodes that are at the same depth together&lt;/strong&gt;. This can be easily achieved using a variable to keep track of the current level you are exploring. &lt;/p&gt;

&lt;p&gt;Using a hash table, you can store every node you process at the right depth. Since we are exploring the left child first, the relative order of the elements at each level will be preserved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;levelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

        &lt;span class="c1"&gt;//Here is where the magic happens&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//Here we create the solution in the expected data structure&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helper&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;We visit N nodes doing constant work per node (adding an element to a hash table has constant amortized time). Therefore, the time complexity is O(N).&lt;/p&gt;

&lt;p&gt;This implementation stores all the nodes in a hash table. Consequently, the space complexity is O(N).&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Level-Order Zigzag Traversal
&lt;/h2&gt;

&lt;p&gt;Given a binary tree, return the &lt;em&gt;zigzag level order&lt;/em&gt; traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fzigzag-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fzigzag-1.png" alt="Level-Order Zigzag Traversal"&gt;&lt;/a&gt;Tree for levellevel-order zigzag traversal&lt;/p&gt;

&lt;p&gt;For this tree, the solution looks like [[8], [14, 4], [2, 5,12,19]].&lt;/p&gt;

&lt;p&gt;Give it a try &lt;a href="https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This problem might seem challenging at first, but you have the tools to solve it. One of the problems above is very similar to this one. I will give you a minute to find it.&lt;/p&gt;

&lt;p&gt;You are right. This is a level-order traversal. The only extra is that we have to process &lt;strong&gt;some levels from left to right and others from right to left&lt;/strong&gt;. We can achieve this easily with two stacks, s1 and s2. &lt;/p&gt;

&lt;p&gt;Imagine we have completed a level from left to right. The last element we pushed to the stack s1 will be the rightmost element at that level of the tree.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Firstly, we create a new partial solution - the solution for the new level.&lt;/li&gt;
&lt;li&gt;We pop the stack s1 and add this element to the partial solution.&lt;/li&gt;
&lt;li&gt;The next level will be explored from right to left. Therefore, we add first the left child and the right child to the other stack s2.&lt;/li&gt;
&lt;li&gt;We keep processing elements from s1 until it is empty.&lt;/li&gt;
&lt;li&gt;In the next iteration, we will process elements from s2 to complete the next level from left to right.&lt;/li&gt;
&lt;li&gt;When we process nodes from s2, we first add their right child and then the left child - LIFO for the next level.&lt;/li&gt;
&lt;li&gt;We do this until both stacks are empty.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zigzagLevelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emplace_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
                &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emplace_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
                &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;Both the time and space complexity are linear. Can you see why?&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Here I have several variants of this problem for you to keep practicing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zigzag t&lt;a href="https://leetcode.com/problems/binary-tree-level-order-traversal-ii/" rel="noopener noreferrer"&gt;ree traversal II&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/n-ary-tree-level-order-traversal/" rel="noopener noreferrer"&gt;Generalize to N nodes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11. Side View of a Tree
&lt;/h3&gt;

&lt;p&gt;Given a binary tree, imagine yourself standing on the &lt;em&gt;right&lt;/em&gt; side of it, return the values of the nodes you can see ordered from top to bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fside-view.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fside-view.png" alt="Side view of a tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The solution for this tree is [16, 19, 18, 13]. Looking from the right side, you cannot see the other nodes because the nodes in the solution "block their view".&lt;/p&gt;

&lt;p&gt;Try coding it &lt;a href="https://leetcode.com/problems/binary-tree-right-side-view/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This may look like a challenging problem, but you have the tools you need to solve it. You need to print the rightmost node of each level. Some of the previous problems look very similar o this one.&lt;/p&gt;

&lt;p&gt;You can solve this problem by modifying the level-order traversal and printing only the last node at each level.&lt;/p&gt;

&lt;p&gt;This is one possible implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rightSideView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                    &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;The analysis is the same as the level-order traversal's.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Here are two variants you can try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solve this problem recursively&lt;/li&gt;
&lt;li&gt;Print the left side instead of the right side&lt;/li&gt;
&lt;li&gt;Print the leaves&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. Vertical-order traversal - Recursive
&lt;/h2&gt;

&lt;p&gt;Given a binary tree, return the &lt;em&gt;vertical order&lt;/em&gt; traversal of its nodes' values.&lt;/p&gt;

&lt;p&gt;For each node at position &lt;code&gt;(X, Y)&lt;/code&gt;, its left and right children respectively will be at positions &lt;code&gt;(X-1, Y-1)&lt;/code&gt; and &lt;code&gt;(X+1, Y-1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Running a vertical line from &lt;code&gt;X = -infinity&lt;/code&gt; to &lt;code&gt;X = +infinity&lt;/code&gt;, whenever the vertical line touches some nodes, we report the values of the nodes in order from top to bottom (decreasing &lt;code&gt;Y&lt;/code&gt; coordinates).&lt;/p&gt;

&lt;p&gt;If two nodes have the same position, then the value of the node that is reported first is the value that is smaller.&lt;/p&gt;

&lt;p&gt;Return a list of non-empty reports in order of &lt;code&gt;X&lt;/code&gt; coordinate. Every report will have a list of values of nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fvertical.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fvertical.png" alt="Vertical order traverse"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The solution for this example is [[4], [6], [12], [21, 14, 23], [20], [24], [25]].&lt;/p&gt;

&lt;p&gt;Code your solution &lt;a href="https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;I bet you are already seeing a solution.&lt;/p&gt;

&lt;p&gt;Every time you move left or right, you can keep track of your X position. This is easy to implement recursively. Every time you move to the left node, the X position decreases by 1. If you move to the right, the X position increases by 1.&lt;/p&gt;

&lt;p&gt;Using a hash table, you can store all the nodes at a certain X position to build the solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;verticalTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="c1"&gt;//Using a lambda function to ensure nodes appear in the expected order&lt;/span&gt;
            &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                 &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
                 &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;else&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;We visit every node once and do constant work per node. However, at the last step where we need to order the nodes at each level. This brings the complexity up. It is not trivial to calculate this new complexity but it is clearly bounded by O(NLogN).&lt;/p&gt;

&lt;p&gt;Since we store all nodes in a hash table, the space complexity is O(N).&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Vertical-order traversal - Iterative
&lt;/h2&gt;

&lt;p&gt;Given a binary tree, return the &lt;em&gt;vertical order&lt;/em&gt; traversal of its nodes' values.&lt;/p&gt;

&lt;p&gt;For each node at position &lt;code&gt;(X, Y)&lt;/code&gt;, its left and right children respectively will be at positions &lt;code&gt;(X-1, Y-1)&lt;/code&gt; and &lt;code&gt;(X+1, Y-1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Running a vertical line from &lt;code&gt;X = -infinity&lt;/code&gt; to &lt;code&gt;X = +infinity&lt;/code&gt;, whenever the vertical line touches some nodes, we report the values of the nodes in order from top to bottom (decreasing &lt;code&gt;Y&lt;/code&gt; coordinates).&lt;/p&gt;

&lt;p&gt;If two nodes have the same position, then the value of the node that is reported first is the value that is smaller.&lt;/p&gt;

&lt;p&gt;Return an list of non-empty reports in order of &lt;code&gt;X&lt;/code&gt; coordinate. Every report will have a list of values of nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fvertical-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.yourdevopsguy.com%2Fwp-content%2Fuploads%2F2020%2F10%2Fvertical-1.png" alt="Vertical tree traversal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The solution for this example is [[4], [6], [12], [21, 14, 23], [20], [24], [25]].&lt;/p&gt;

&lt;p&gt;Test your solution &lt;a href="https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Based on my explanation for the previous problem and your understanding of BFS, you will be able to write the iterative version of the algorithm that solves the problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;verticalTraversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TreeNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sd&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Complexity
&lt;/h4&gt;

&lt;p&gt;I will leave this as an exercise for you. If you need hints, check the previous problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;This was supposed to be an article on how to traverse a tree. It ended up being an excuse to work on recursive and iterative solutions to the same problem. We can extract a few learnings from this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In general, it is not trivial to translate a recursive algorithm into an iterative. However, this is trivial for &lt;a href="https://en.wikipedia.org/wiki/Tail_call#Relation_to_while_construct" rel="noopener noreferrer"&gt;tail-recursive&lt;/a&gt; functions.&lt;/li&gt;
&lt;li&gt;Recursive solutions can lead to stack overflow. Always consider iterative solutions (limited by RAM size).&lt;/li&gt;
&lt;li&gt;Some problems have straightforward recursive solutions and complicated iterative implementations.&lt;/li&gt;
&lt;li&gt;Recursive solutions tend to be slower because of the stack calls. However, your focus should be on having a working code that is maintainable and readable. Only optimize after using a profiler and finding the real bottlenecks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I have said before, it is not about solving a million problems or spending a million hours. &lt;strong&gt;What is important is what you get out of each hour&lt;/strong&gt;. We have also seen that from a seemingly simple problem we have been able to extract a lot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“No problem is too small or too trivial if we can really do something about it.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Richard_Feynman" rel="noopener noreferrer"&gt;Richard Feynman&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The aim of this entry is to &lt;strong&gt;make you think about each problem&lt;/strong&gt;. We have seen 13 ways to traverse a tree. We have work on recursive and iterative implementations. &lt;strong&gt;You have become smarter by going through this article&lt;/strong&gt;. As the next logical step, I invite you to read my article on &lt;a href="https://www.yourdevopsguy.com/all-you-need-to-know-about-dynamic-programming/" rel="noopener noreferrer"&gt;dynamic programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you found this article helpful, please share it. Chances are more people will find it useful too. You can help someone pass their exams, a job interview, or get them unblocked at work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to have a look at my blog &lt;a href="http://www.yourdevopsguy.com" rel="noopener noreferrer"&gt;www.yourdevopsguy.com&lt;/a&gt; and connect with me on &lt;a href="//www.twitter.com/@codinglanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What is the difference between a junior and a senior software developer? 15 things I wish I had known sooner</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Sun, 13 Sep 2020 06:26:00 +0000</pubDate>
      <link>https://dev.to/codinglanguages/what-is-the-difference-between-a-junior-and-a-senior-software-developer-15-things-i-wish-i-had-known-sooner-4hpl</link>
      <guid>https://dev.to/codinglanguages/what-is-the-difference-between-a-junior-and-a-senior-software-developer-15-things-i-wish-i-had-known-sooner-4hpl</guid>
      <description>&lt;p&gt;This article was originally published in my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the difference between a junior and a senior developer?
&lt;/h1&gt;

&lt;p&gt;When I first started coding I also felt lost and overwhelmed. I thought I needed to focus only on my coding skills to get promoted to senior. Over time, I realized the difference between a junior and a senior developer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Senior software engineers design solutions to complex, open-ended problems, with no guidance. They gather requirements, design solutions, tasks, code, deploy and maintain the system. They care about the system's performance, security, testing, extensibility, scaling, instrumentation, and maintainability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is something I later learned as part of a training session at Amazon on how to move to the next level. &lt;strong&gt;They expect seniors to figure out how to solve problems on their own, while juniors need guidance&lt;/strong&gt;. This does not mean they know everything. This includes knowing when and how to ask questions, which takes experience. &lt;strong&gt;Senior engineers take tasks that no one else wants to do and that cannot be solved with a simple Google search.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not equate years of experience with wisdom. &lt;strong&gt;There are people with 10 years of experience and people who have experienced the same year ten times.&lt;/strong&gt; I recommend never getting too comfortable with what you are doing to keep growing.&lt;/p&gt;

&lt;p&gt;This is a list of tips I wrote during my first year as a software developer. They come mostly from making mistakes and observing team leaders and principal engineers.&lt;/p&gt;

&lt;h1&gt;
  
  
  15 things I wish I had known sooner
&lt;/h1&gt;

&lt;h2&gt;
  
  
  How to work more efficiently
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. For every task you work on have a clear definition of done&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This helps with planning, keeps you focused on what you need to do, and makes it easier to document your work. Even for open-ended tasks, there should be a clear goal: for instance, a decision to use technology A or B.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Define the scope
&lt;/h3&gt;

&lt;p&gt;Make sure the &lt;strong&gt;scope of the task is well defined too&lt;/strong&gt;. Do not waste time on things out of your or your team's scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Time estimates are hard
&lt;/h3&gt;

&lt;p&gt;I have usually overlooked at the time I needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Design and &lt;strong&gt;choose a solution&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change or add new &lt;strong&gt;tests&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get my colleagues to approve my &lt;strong&gt;pull request&lt;/strong&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Mindset
&lt;/h3&gt;

&lt;p&gt;Have a look at the &lt;a href="https://www.aboutamazon.com/working-at-amazon/our-leadership-principles"&gt;Amazon Leadership principles&lt;/a&gt;. They provide &lt;strong&gt;a good mindset&lt;/strong&gt; for your transition to a senior level, especially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bias for action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dive deep&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Earn trust&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disagree and commit&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes principles may contradict, so take make &lt;strong&gt;a decision based on your situation&lt;/strong&gt;. A senior developer does not just write code but is a leader that takes impactful decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to optimize your work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5. Automate
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Automate&lt;/strong&gt; as much as you can. It is obvious that you gain a lot of time in the medium and long term, but this has to do with the number of iterations, not time. You need to have a &lt;em&gt;rule to decide when to automate&lt;/em&gt; a task. Personally, if I find myself doing twice something that I can automate, it is time to write a script.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Work incrementally
&lt;/h3&gt;

&lt;p&gt;Do not write 1000 lines of code before you start testing it. &lt;strong&gt;Work and&lt;/strong&gt; &lt;strong&gt;verify your changes&lt;/strong&gt; &lt;strong&gt;incrementally&lt;/strong&gt;. Check if the code can compile, or you forgot to import a library (good IDEs with this). Doing things &lt;strong&gt;right from the start&lt;/strong&gt; is easier than redoing sloppy work. From the outset, write readable code, unit tests, do small refactors, etc. &lt;/p&gt;

&lt;h3&gt;
  
  
  7. Premature optimization is the root of all evil
&lt;/h3&gt;

&lt;p&gt;Avoid &lt;strong&gt;premature optimization&lt;/strong&gt;. This is not the same as not using the most appropriate &lt;a href="https://dev.to/codinglanguages/how-to-learn-not-memorize-any-algorithm-or-data-structure-analysis-of-20-problem-solving-techniques-you-must-know-d77"&gt;data structures and algorithms&lt;/a&gt; from the beginning. Your focus should be to &lt;strong&gt;write code that works and later make it efficient&lt;/strong&gt;. Write code, use a profiler to find the &lt;em&gt;real bottlenecks&lt;/em&gt; and focus on optimizing them. &lt;/p&gt;

&lt;h3&gt;
  
  
  8. Get a rubber duck
&lt;/h3&gt;

&lt;p&gt;Before you ask for help, get a &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging"&gt;rubber duck&lt;/a&gt;. It can be a virtual one. Before you ask for help, &lt;strong&gt;explain the problem&lt;/strong&gt; to your rubber duck and how you are trying to solve it. Go through your code &lt;strong&gt;line-by-line&lt;/strong&gt;. Chances are you will find the solution. If not, &lt;strong&gt;you will be able to better articulate your question&lt;/strong&gt; to your colleague. &lt;/p&gt;

&lt;h3&gt;
  
  
  9. Revise your assumptions
&lt;/h3&gt;

&lt;p&gt;When things go wrong, &lt;strong&gt;check your assumptions&lt;/strong&gt;. I wasted long hours debugging issues that came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reading the &lt;em&gt;wrong configuration file&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;using &lt;em&gt;outdated information&lt;/em&gt; from an internal wiki page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;problems with someone else's code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;copy-paste related errors&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logging and quick chats can speed things up.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Read the documentation
&lt;/h3&gt;

&lt;p&gt;I have also avoided reading the documentation out of pure laziness. If your team's documentation is unclear or lacks information, &lt;strong&gt;improve it&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Beware of comments
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Code never lies, &lt;strong&gt;comments&lt;/strong&gt; sometimes do." — &lt;a href="https://en.wikipedia.org/wiki/Ron_Jeffries"&gt;Ron Jeffries&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best comment is the one you don't have to write. &lt;strong&gt;Comments, like code, can rot&lt;/strong&gt; &lt;strong&gt;and be misleading&lt;/strong&gt;. If you are going to write a comment, make sure it is the best comment you can write&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do not state the obvious &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be brief and precise&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check your grammar and punctuation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove comments that produce noise&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  12. Learn to communicate
&lt;/h3&gt;

&lt;p&gt;Coding has more human interaction that people think. You need to interact with people to define tasks and ask questions. Also, when you read and write documentation and comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consider clear and effective communication as part of your job requirements&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to approach complex, open-ended tasks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  13. Ask questions
&lt;/h3&gt;

&lt;p&gt;It is key to &lt;strong&gt;clarify&lt;/strong&gt; the problem before you start working on it. Some of the following questions can help you gather better requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What are the inputs your system expects?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is an invalid input and what to do when you receive one?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What output do you need to produce?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is our service level agreement (SLA)?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How many users do we expect? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How many requests per second?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do we need to deal with internationalization?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do we need strong consistency in our database or is eventual consistency enough?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes you will not have all the information you need to start solving the problem. Chances are no one will and it is your responsibility to figure it all out. &lt;strong&gt;The moment you start taking this type of task you will know you are operating at a senior level.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  14. Design on paper first
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;pen and paper&lt;/strong&gt; or a &lt;strong&gt;whiteboard&lt;/strong&gt; to sketch a solution before you start coding. Unless you are solving a trivial problem, try to come up with different alternatives. Then, &lt;strong&gt;try to break your own design&lt;/strong&gt;. Ask yourself questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Where &lt;strong&gt;can&lt;/strong&gt; the system &lt;strong&gt;break&lt;/strong&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What are the &lt;strong&gt;bottlenecks&lt;/strong&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are we relying on &lt;strong&gt;third parties&lt;/strong&gt;? What happens when something goes wrong on their end?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can we use a cache to improve performance? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is an appropriate TTL? &lt;/li&gt;
&lt;li&gt;What is the worst thing that can happen if we temporarily serve stale content?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How can we log and monitor the system?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Document your choices, the rationale behind them, and potential risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus tip
&lt;/h2&gt;

&lt;p&gt;I think I read this somewhere in an internal wiki page, but it helped me see where I was falling short.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Do not be a one-trick pony
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If you only know how to do only one thing, it is likely that you have gaps in other areas&lt;/strong&gt;. Learn other programming languages. Create some machine learning prototypes, even if you are an Android developer. If you are a front-end developer, learn about backend or dive into the internals of Linux. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You don't need to become an expert, but you will an appreciation of how the different pieces fit together&lt;/strong&gt;. You may learn a thing or two from other areas that you can apply in your career. You may find that you love something new you had never tried and change careers!&lt;/p&gt;

&lt;p&gt;PS: I hope you found this useful. If so, like and share this article, visit my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;, and let's connect on &lt;a href="https://twitter.com/CodingLanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>cpp</category>
      <category>productivity</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to learn data structures and algorithms. 20 problem-solving techniques you must know</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Thu, 03 Sep 2020 16:28:00 +0000</pubDate>
      <link>https://dev.to/codinglanguages/how-to-learn-not-memorize-any-algorithm-or-data-structure-analysis-of-20-problem-solving-techniques-you-must-know-d77</link>
      <guid>https://dev.to/codinglanguages/how-to-learn-not-memorize-any-algorithm-or-data-structure-analysis-of-20-problem-solving-techniques-you-must-know-d77</guid>
      <description>&lt;p&gt;This article was originally published in my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the article I wish I had read when I started coding. Programming is about solving problems and here I will dive deep into 20 problem-solving techniques, with code samples, big O analysis, and challenges so that you can master them.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/codinglanguages/how-to-ace-coding-interviews-the-ultimate-guide-5567"&gt;this article&lt;/a&gt;, I outlined a high-level strategy to prepare for your next coding interview as well as the top mistakes to avoid. Here, I will dive deep into 20 problem-solving techniques that you must know to excel at your next interview. They have helped me at work too and even given me ideas for a side project I am working on. Also, the last section includes a &lt;strong&gt;step-by-step guide to learn (not memorize) any algorithm or data structure&lt;/strong&gt;, with 2 examples.&lt;/p&gt;

&lt;p&gt;I have grouped these techniques in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pointer based&lt;/li&gt;
&lt;li&gt;Recursion based&lt;/li&gt;
&lt;li&gt;Sorting and searching&lt;/li&gt;
&lt;li&gt;Extending basic data structures&lt;/li&gt;
&lt;li&gt;Miscellanea&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will explain each of them, show how to apply them to coding problems, and leave you some exercises so that you can practice on your own.&lt;/p&gt;

&lt;p&gt;This list is part of the study notes that I took before I applied to Amazon. I hope they will be as useful to you as they have been to me.&lt;/p&gt;

&lt;p&gt;For your convenience, I have copied here the problem statements, but I have left links to all of the exercises. You can copy-paste my solution and play around with it. I strongly recommend you code your solution and see if it passes the tests.&lt;/p&gt;

&lt;p&gt;Some of the questions are better explained through an image or diagram. For these, I have left a comment asking you to open the link to get a graphical description of the problem.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pointer based techniques
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Two Pointers
&lt;/h2&gt;

&lt;p&gt;This technique is very useful on &lt;em&gt;sorted arrays&lt;/em&gt; and arrays whose elements we want to &lt;em&gt;group&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The idea is to use two (or more pointers) to split the array into different areas or groups based on some condition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elements smaller than, equal to and greater than a certain value&lt;/li&gt;
&lt;li&gt;Elements whose sum is too small or too large&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following examples will help you understand this principle.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/"&gt;Two sum&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your returned answers (both index1 and index2) are not zero-based.&lt;/li&gt;
&lt;li&gt;You may assume that each input would have exactly one solution and you may not use the same element twice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: numbers = [2,7,11,15], target = 9&lt;/li&gt;
&lt;li&gt;Output: [1,2]&lt;/li&gt;
&lt;li&gt;Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Since the array &lt;em&gt;a&lt;/em&gt; is sorted, we know that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The largest sum is equal to the sum of the last 2 elements&lt;/li&gt;
&lt;li&gt;The smallest sum is equal to the sum of the first 2 elements &lt;/li&gt;
&lt;li&gt;For any index &lt;em&gt;i&lt;/em&gt; in [0, a.size() - 1) =&amp;gt; a[i + 1] &amp;gt;= a[i]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, we can design the following algorithm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We keep 2 pointers: &lt;em&gt;l&lt;/em&gt;, starting at the first element of the array, and &lt;em&gt;r&lt;/em&gt; starting at to the last.&lt;/li&gt;
&lt;li&gt;If the sum of a[l] + a[r] is smaller than our target, we increment l by one (to change the smallest operand in the addition for another one equal or larger than it at &lt;em&gt;l+1&lt;/em&gt;); if it is larger than the target, we decrease r by one (to change our largest operand for another one equal or smaller at &lt;em&gt;r-1&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;We do this until a[l] + a[r] equals our target or l and r point to the same element (since we cannot use the same element twice) or have crossed, indicating there is no solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a simple C++ implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; twoSum(const vector&amp;lt;int&amp;gt;&amp;amp; a, int target) {
        int l = 0, r = a.size() - 1;
        vector&amp;lt;int&amp;gt; sol;
        while(l &amp;lt; r) {
            const int sum = a[l] + a[r];
            if(target == sum){
                sol.push_back(l + 1); 
                sol.push_back(r + 1); 
                break;
            } else if (target &amp;gt; sum) {
                ++l;
            } else {
                --r;
            }
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The time complexity is O(N), since we may need to traverse the N elements of the array to find the solution. &lt;/p&gt;

&lt;p&gt;The space complexity is O(1), since we only need two pointers, regardless of how many elements the array contains.&lt;/p&gt;

&lt;p&gt;There are other ways of solving this problem (using a hash table, for example), but I have used it just as an illustration of the two pointer technique.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Here are two variations of this exercise: &lt;a href="https://leetcode.com/problems/3sum/"&gt;three sum&lt;/a&gt; and &lt;br&gt;
&lt;a href="https://leetcode.com/problems/4sum/"&gt;four sum&lt;/a&gt;. They can be solved similarly by &lt;strong&gt;reducing&lt;/strong&gt; them to this very same problem. &lt;/p&gt;

&lt;p&gt;This is a very common technique: &lt;strong&gt;transform a problem whose solution you don't know to a problem that you can solve&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/remove-duplicates-from-sorted-array/"&gt;Remove duplicates from array&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a sorted array, nums, remove the duplicates in-place such that each element appears only once and return the new length.&lt;/p&gt;

&lt;p&gt;Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Given nums = [1,1,2],&lt;/li&gt;
&lt;li&gt;Output = 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Given nums = [0,0,1,1,1,2,2,3,3,4],&lt;/li&gt;
&lt;li&gt;Output = 5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It doesn't matter what values are set beyond the returned length.&lt;/p&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The array is &lt;strong&gt;sorted&lt;/strong&gt; and we want to move duplicates to the end of the array, which sounds a lot like &lt;strong&gt;grouping based on some condition&lt;/strong&gt;. How would you solve this problem using two pointers?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will need one pointer to iterate through the array, &lt;em&gt;i&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;And a second pointer, &lt;em&gt;n&lt;/em&gt;, one to define the area that contains no duplicates: [0,n].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The logic is as follows. If the values of the elements at index &lt;em&gt;i&lt;/em&gt; (except &lt;em&gt;i&lt;/em&gt; = 0) and &lt;em&gt;i-1&lt;/em&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same, we don’t do anything - this duplicate will be overwritten by the next unique element in &lt;em&gt;a&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Different: we add &lt;em&gt;a[i]&lt;/em&gt; to the section of the array that contains no duplicates - delimited by &lt;em&gt;n&lt;/em&gt;, and increment n by one.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int removeDuplicates(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
    if(nums.empty())
        return 0;
    int n = 0;
    for(int i = 0; i &amp;lt; nums.size(); ++i){
        if(i == 0 || nums[i] != nums[i - 1]){
            nums[n++] = nums[i];
        }
    }
    return n;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This problem has linear time complexity and constant space complexity (it is usually the case for problems solved using this technique).&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/sort-colors/"&gt;Sort colors&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue. Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.&lt;br&gt;
Note: You are not supposed to use the library's sort function for this problem.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [2,0,2,1,1,0]&lt;/li&gt;
&lt;li&gt;Output: [0,0,1,1,2,2]&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The groups this time are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller than 1&lt;/li&gt;
&lt;li&gt;Equal to 1&lt;/li&gt;
&lt;li&gt;Larger than 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we can achieve with 3 pointers. &lt;/p&gt;

&lt;p&gt;This implementation is a bit tricky, so make sure you test it thoroughly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void sortColors(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
    int smaller = 0, eq = 0, larger = nums.size() - 1;
    while(eq &amp;lt;= larger){
        if(nums[eq] == 0){
            swap(nums[smaller], nums[eq]);
            ++smaller; ++eq;
        } else if (nums[eq] == 2) {
            swap(nums[larger], nums[eq]);
            --larger;
        } else {
            eq++;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since need to traverse the array to sort it, the time complexity is O(N). The space complexity is O(1).&lt;/p&gt;

&lt;p&gt;Just as a curiosity, this is an instance of the &lt;a href="https://en.wikipedia.org/wiki/Dutch_national_flag_problem"&gt;National Dutch flag&lt;/a&gt; problem described by Dijkstra.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.geeksforgeeks.org/nth-node-from-the-end-of-a-linked-list/"&gt;Remove the n-th node from the end of a linked list&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a Linked List and a number n, write a function that returns the value at the n-th node from the end of the Linked List.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This is one of the most common variations of the two-pointer technique: introducing &lt;strong&gt;an offset&lt;/strong&gt; so that one of the pointers reaches a certain condition, the other one is in the position you are interested in.&lt;/p&gt;

&lt;p&gt;In this case, if we move one of the pointers, &lt;em&gt;f&lt;/em&gt;, n times and then start advancing both at the same time by one node, when &lt;em&gt;f&lt;/em&gt; reaches the end of the list the other pointer, &lt;em&gt;s&lt;/em&gt;, will point to the node right before the node we want to delete.&lt;/p&gt;

&lt;p&gt;Make sure you define what n = 1 means (last element or the element before the last element?), and avoid off-by-one errors.&lt;/p&gt;

&lt;p&gt;The time and space complexity are the same as the previous problems'.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pointers moving at different speeds
&lt;/h2&gt;

&lt;p&gt;Now, you will have two pointers moving at different &lt;em&gt;speeds&lt;/em&gt;: at every iteration, one of the pointers will advance one node and the other will advance two nodes. We can use this variation to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get to the middle element of a linked list&lt;/li&gt;
&lt;li&gt;Detect cycles in a linked list&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual, it will become clearer once I present some examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/middle-of-the-linked-list/"&gt;Find the middle node of a linked list of unknown size&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a non-empty, singly linked list with head node head, return a middle node of the list. If there are two middle nodes, return the second middle node.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [1,2,3,4,5]&lt;/li&gt;
&lt;li&gt;Output: Node 3 from this list&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Solving this problem in 2 passes is easy: on the first pass we compute the size of the list, &lt;em&gt;L&lt;/em&gt;, and on the second pass we only advance &lt;em&gt;L/2&lt;/em&gt; nodes to find the element at the middle of the list. This approach has linear complexity in time and constant in space.&lt;/p&gt;

&lt;p&gt;How can we use 2 pointers to find the middle element in one single pass?&lt;/p&gt;

&lt;p&gt;If one of the pointers, &lt;em&gt;f&lt;/em&gt;, moves twice as fast as the other one &lt;em&gt;s&lt;/em&gt;, when &lt;em&gt;f&lt;/em&gt; reaches the end, &lt;em&gt;s&lt;/em&gt; will be in the middle of the list.&lt;/p&gt;

&lt;p&gt;Here's my solution in C++. Make sure you take into account edge cases (empty list, lists of odd and even sizes, etc) when you test your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ListNode* middleNode(ListNode* head) {
       ListNode* slow = head;
       ListNode* fast = head;

       while (fast != nullptr &amp;amp;&amp;amp; fast-&amp;gt;next != nullptr) {
           slow = slow-&amp;gt;next;
           fast = fast-&amp;gt;next-&amp;gt;next;
       }
       return slow; 
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/linked-list-cycle/"&gt;Detect cycle in a linked list&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where the tail connects to. If pos is -1, then there is no cycle in the linked list.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: head = [3,2,0,-4], pos = 1&lt;/li&gt;
&lt;li&gt;Output: true&lt;/li&gt;
&lt;li&gt;Explanation: There is a cycle in the linked list, where the tail connects to the second node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The simplest solution is to add all the nodes to a hash set. When we traverse the list, if we get to a node that has already been added to the set, there is a cycle. If we get to the end of the list, there are no cycles. &lt;/p&gt;

&lt;p&gt;This has a time complexity of O(L), being &lt;em&gt;L&lt;/em&gt; the length of the list, and space complexity of O(L), since in the &lt;em&gt;worst&lt;/em&gt; case - no cycles - we need to add all the elements of the list to the hash set.&lt;/p&gt;

&lt;p&gt;Time complexity cannot be improved. However, space complexity can be reduced to O(1). Think for a minute how this can be achieved with two pointers moving at different speeds.&lt;/p&gt;

&lt;p&gt;Let's call these pointers fast and slow. For each node slow visits, fast will move two nodes forward. Why? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If fast reaches the end of the list, the list does not contain any cycles.&lt;/li&gt;
&lt;li&gt;If there is a cycle, since fast moves twice as fast as slow, it is just a matter of time (iterations, to be more precise) that the fast node catches the slow one, pointing both to the same node, which indicates the existence of a cycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's translate this solution into code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool hasCycle(ListNode *head) {
        ListNode* slow = head, *fast = head;
        while(fast){
            slow = slow-&amp;gt;next;
            fast = fast-&amp;gt;next;
            if(!fast)
                break;
            fast = fast-&amp;gt;next;
            if(slow == fast)
                return true;
        }
        return false;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/find-the-duplicate-number/"&gt;Find the duplicate number&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array, nums, containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [1,3,4,2,2]&lt;/li&gt;
&lt;li&gt;Output: 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This is the same problem/solution as the previous problems, for arrays instead of linked lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int findDuplicate(const vector&amp;lt;int&amp;gt;&amp;amp; nums) {
    int slow = nums[0], fast = slow; 
    do {
        slow = nums[slow];
        fast = nums[nums[fast]];
    } while(slow != fast);

    slow = nums[0];
    while(slow != fast){
        slow = nums[slow];
        fast = nums[fast];            
    }

    return slow;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Here are more problems that can be solved using this technique:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/intersection-of-two-linked-lists/"&gt;Detect if two linked lists have elements in common&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/happy-number/"&gt;Happy numbers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Sliding Window
&lt;/h2&gt;

&lt;p&gt;The sliding window technique eases the task of finding optimal &lt;em&gt;chunks of contiguous data&lt;/em&gt; that meet a certain condition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Longest subarray that …&lt;/li&gt;
&lt;li&gt;Shortest substring containing …&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can think of it as another variation of the two pointer technique, where pointers are updated separately based on a certain condition. Below is the basic recipe for this type of problems, in pseudocode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create two pointers, l, and r
Create variable to keep track of the result (res)

Iterate until condition A is satisfied:
  Based on condition B:
update l, r or both
Update res
Return res
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/longest-substring-without-repeating-characters/"&gt;Longest Substring Without Repeating Characters&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a string, find the length of the longest substring without repeating characters.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: "abcabcbb"&lt;/li&gt;
&lt;li&gt;Output: 3 &lt;/li&gt;
&lt;li&gt;Explanation: The answer is "abc", with the length of 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Find the length of the longest substring without repeating characters&lt;/em&gt; sounds a lot like &lt;em&gt;finding optimal *chunks of contiguous data&lt;/em&gt; that meet a certain condition.*&lt;/p&gt;

&lt;p&gt;Based on the recipe I described above, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two pointers, &lt;em&gt;l&lt;/em&gt; and &lt;em&gt;r&lt;/em&gt;, to define our substring &lt;em&gt;s&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;A variable, &lt;em&gt;sol&lt;/em&gt;, to store the length of the longest substring we have seen so far.&lt;/li&gt;
&lt;li&gt;A way of keeping track of the characters that form &lt;em&gt;s&lt;/em&gt;: a set, &lt;em&gt;seen&lt;/em&gt;, will be perfect for this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While iterating through the string:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the current character is in &lt;em&gt;seen*you have to increment *l&lt;/em&gt; to start removing elements from the beginning of our &lt;em&gt;s&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Otherwise, add the character to &lt;em&gt;seen&lt;/em&gt;, move &lt;em&gt;r&lt;/em&gt; forward and update &lt;em&gt;sol&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int lengthOfLongestSubstring(const string&amp;amp; s) {
    int sol = 0;
    int l = 0, r = 0;
    unordered_set&amp;lt;int&amp;gt; seen;
    while(r &amp;lt; s.size()) {
        const auto find = seen.find(s[r]);
        if(find == seen.end()) {
            sol = max (sol, r - l + 1);
            seen.insert(s[r]);
            ++r;
        } else {
            seen.erase(s[l++]);
        }
    }
    return sol;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;For more practice, you can try the following problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/permutation-in-string/solution/"&gt;Permutation of a string&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/max-consecutive-ones-iii/"&gt;Max consecutive ones&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There might be simpler solutions but focus on using this technique to get a better grasp of it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Recursion based techniques
&lt;/h1&gt;

&lt;h2&gt;
  
  
  4. Dynamic Programming
&lt;/h2&gt;

&lt;p&gt;I already published an article on this topic that you can find &lt;a href="https://www.yourdevopsguy.com/all-you-need-to-know-about-dynamic-programming-ckd9volta00g1yws18oi97pjf"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Backtracking
&lt;/h2&gt;

&lt;p&gt;The idea behind backtracking is to explore all the potential solutions for a problem, in a smart way. It builds candidate solutions incrementally and as soon as it determines that a candidate solution is not viable, it &lt;em&gt;backtracks&lt;/em&gt; to a previous state and tries the next candidate.&lt;/p&gt;

&lt;p&gt;Backtracking problems present you with a list of choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should you place &lt;em&gt;this piece&lt;/em&gt; in &lt;em&gt;this position&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;Should you add &lt;em&gt;this number&lt;/em&gt; to the set?&lt;/li&gt;
&lt;li&gt;Should you try &lt;em&gt;this number&lt;/em&gt; in &lt;em&gt;this position&lt;/em&gt; next?&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you have picked one of the options, it will get you a new list of choices, until you reach a state where there are no more choices: either you arrived at a solution or there is no solution.&lt;/p&gt;

&lt;p&gt;Visually, you are moving from the root of a tree with every choice, until you get to a leaf. The basic high-level recipe (in pseudocode) for a backtracking algorithm is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;boolean backtracking(Node n){
    if(isLeaf(n) {
        if(isSolution(candidate)){
            sol.add(candidate);
            return true;
        } else {
            return false;
        }
    }

    //Explore all children
    for(child in n) {
        if(backtracking(child))
            return true;
    }

    return false;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This can of course change depending on the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need &lt;em&gt;all&lt;/em&gt; solutions, the helper function returns nothing (void) to avoid stopping when we find the first solution.&lt;/li&gt;
&lt;li&gt;To backtrack, you may have to bring your program to a previous state before you can move forward&lt;/li&gt;
&lt;li&gt;After you choose a child, you need to detect if the candidate solution is viable or not: the definition of viable depends on the problem&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the core idea is the same: examine, in a systematic way, all paths and backtrack as soon as the current path is no longer viable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/n-queens/"&gt;N queens&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other&lt;br&gt;
Given an integer n, return all distinct solutions to the n-queens puzzle.&lt;/p&gt;

&lt;p&gt;Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 4&lt;/li&gt;
&lt;li&gt;Output: [
[".Q..",  // Solution 1
"...Q",
"Q...",
"..Q."],&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;["..Q.",  // Solution 2&lt;br&gt;
  "Q...",&lt;br&gt;
  "...Q",&lt;br&gt;
  ".Q.."]&lt;br&gt;
]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This is a classic backtracking problem&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need all solutions here, which is why the recursive function returns nothing as I explained in the introduction of this section.&lt;/li&gt;
&lt;li&gt;Do not worry too much about the &lt;em&gt;isViableSolution&lt;/em&gt; function for now. Try to see the recipe I gave (slightly modified) you in action.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; solveNQueens(int n) {
        vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; solutions;

        /** 

        This is usually solved with a vector of integers, 
        where each integer represents the position of the queen in that column.
        This particular problem expects strings.
        Each string represents a column
        */
        vector&amp;lt;string&amp;gt; board(n, string(n, '.'));

        solveBoard(solutions, board, 0, n);   

        return solutions;
    }

    void solveBoard(vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt;&amp;amp; solutions, vector&amp;lt;string&amp;gt;&amp;amp; board, int col, int n){
        if(col == n){
            solutions.push_back(board);
            return;
        }

        for(int row = 0; row &amp;lt; n; row++){
            if(isViableSolution(board, row, col)){                
                board[row][col] = 'Q';
                solveBoard(solutions, board, col + 1, n);
                //Backtracking - we bring our board to the previous state
                board[row][col] = '.';  
            }
        }        
    }

    bool isViableSolution(vector&amp;lt;string&amp;gt;&amp;amp; board, int row, int col){
        int n = board.size(); 

        for(int x = 1; x &amp;lt;= col; x++){
            if(board[row][col-x] == 'Q')
                return false;
        }

        for(int x = 1; row - x &amp;gt;= 0 &amp;amp;&amp;amp; col &amp;gt;= x; x++){
            if(board[row-x][col-x] == 'Q') 
                return false;
        }

        for(int x = 1; row + x &amp;lt; n &amp;amp;&amp;amp; col &amp;gt;= x; x++){
            if(board[row+x][col-x] == 'Q') 
                return false;
        } 

        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/letter-combinations-of-a-phone-number/"&gt;Letter combination&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent (check the link for diagram). Note that 1 does not map to any letters.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: "23"&lt;/li&gt;
&lt;li&gt;Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;For every number in the input, you have several letters to choose from. If you can draw a tree (this is what I do) where the branches are born from the different choices you take, chances are that you can apply backtracking.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Before you start solving any problem, try different approaches: dynamic programming, greedy algorithms, divide and conquer, a combination of algorithms and data structures, etc. Coding is the &lt;em&gt;last step&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My solution, in C++:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;string&amp;gt; letterCombinations(const string &amp;amp;digits) {
    if(digits.empty())
        return {};
    const vector&amp;lt;string&amp;gt; letters {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    vector&amp;lt;string&amp;gt; sol;
    string candidate (digits.size(), ' ');
    h(sol, 0, candidate, letters, digits);
    return sol;
}

void h(vector&amp;lt;string&amp;gt; &amp;amp;sol, int idx, string &amp;amp;candidate, const vector&amp;lt;string&amp;gt; &amp;amp;letters, const string &amp;amp;digits){
    if(idx == digits.size()){
        sol.push_back(candidate);
        return;
    }

    for(const char &amp;amp;c : letters[digits[idx] - '0']) {
        candidate[idx] = c;
        h(sol, idx + 1, candidate, letters, digits);            
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since I knew already the size of the solution, I initialize my &lt;code&gt;candidate&lt;/code&gt; with that size and just modified the character at position &lt;code&gt;idx&lt;/code&gt;. If the size is not known, this can be done instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string candidate; //instead of string candidate (digits.size(), ' ');
…
for(const char &amp;amp;c : letters[digits[idx] - '0']) {
    candidate.push_back(c);
    h(sol, idx + 1, candidate, letters, digits);            
    candidate.pop_back();
}    
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/sudoku-solver/"&gt;Sudoku solver&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Write a program to solve a Sudoku puzzle by filling the empty cells. Open the link to get a longer description, including an image of the puzzle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;In an interview, unless you have plenty of time, you will not need to implement &lt;em&gt;isViableSolution&lt;/em&gt;, just to sketch it. I know a colleague who got this question in an on-site. &lt;/p&gt;

&lt;p&gt;Even though the code is long, it is mostly because of &lt;em&gt;isViableSolution&lt;/em&gt;. Otherwise, it is not very different from other backtracking problems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void solveSudoku(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board){
        helper(board);
    }

    bool helper(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board, int row = 0, int col = 0) {
        if(col == size){
           col = 0;
           ++row;
            if(row == size){
                return true;
            }
        }

        if(board[row][col] != '.'){
            return helper(board, row, col + 1);
        }

        for(char i = '1'; i &amp;lt;= '9'; ++i){
            if(isViableSolution(board, row, col, i)){
                board[row][col] = i;
                if (helper(board, row, col + 1))
                    return true;
            }
        }
        board[row][col] = '.';
        return false;
    }

    bool isViableSolution(const vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board, int row, int col, char c){
        for(const auto&amp;amp; n : board[row]){
            if(n == c)
                return false;
        }

        for(int r = 0; r &amp;lt; size; ++r){
            if(board[r][col] == c)
                return false;
        }

        const int br = row / nsize;
        const int bc = col / nsize;

        for(int i = 0; i &amp;lt; nsize ; ++i){
            for(int j = 0; j &amp;lt; nsize; ++j){
                if(c == board[3 * br + i][3 * bc + j])
                    return false;
            }
        }

        return true;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/n-queens-ii/"&gt;N queens II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/generate-parentheses/solution/"&gt;Generate parenthesis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://leetcode.com/problems/palindrome-partitioning/"&gt;Palindromic partitioning&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/letter-tile-possibilities/"&gt;Letter tile possibilities&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Subsets
&lt;/h2&gt;

&lt;p&gt;I have created a generic separate section for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subsets&lt;/li&gt;
&lt;li&gt;Combinations &lt;/li&gt;
&lt;li&gt;Permutations &lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because conceptually they are similar: take the elements of a container (array, string, etc) and create subsets from them according to some rule(s).&lt;/p&gt;

&lt;p&gt;You will notice that most of these are backtracking problems or very similar.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/subsets/"&gt;Subsets&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a set of distinct integers, nums, return all possible subsets (&lt;a href="https://en.wikipedia.org/wiki/Power_set"&gt;the power set&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Note: The solution set must not contain duplicate subsets.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: nums = [1,2,3]&lt;/li&gt;
&lt;li&gt;Output:
[ [3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[] ]&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;For every index &lt;em&gt;i&lt;/em&gt;, you need to generate two solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One that contains a[i]&lt;/li&gt;
&lt;li&gt;One that does not contain a[i]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until you get to the end of the array. &lt;/p&gt;

&lt;p&gt;Here’s a simple implementation of what we have discussed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; subsets(const vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        vector&amp;lt;int&amp;gt; partial;
        h(sol, partial, nums);
        return sol;
    }
    void h(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; sol, vector&amp;lt;int&amp;gt;&amp;amp; partial, const vector&amp;lt;int&amp;gt;&amp;amp; nums, int idx = 0){
        sol.push_back(partial);
        if(idx == nums.size()){
            return;
        }

        for(int i = idx; i &amp;lt; nums.size(); ++i){
            partial.push_back(nums[i]);
            h(sol, partial, nums, i + 1);
            partial.pop_back();
        }        
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/subsets-ii/"&gt;Subsets - containing duplicates&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a variant of the previous problem. Try playing around with my code to see if you can change it to meet the new requirement. You have to change less than 5 lines.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; subsetsWithDup(vector&amp;lt;int&amp;gt; nums) {
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        vector&amp;lt;int&amp;gt; partial;
        sort(nums.begin(), nums.end());
        h(sol, partial, nums);
        return sol;
    }
    void h(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; sol, vector&amp;lt;int&amp;gt;&amp;amp; partial, const vector&amp;lt;int&amp;gt;&amp;amp; nums, int idx = 0){
        sol.push_back(partial);
        if(idx == nums.size()){
            return;
        }

        for(int i = idx; i &amp;lt; nums.size(); ++i){
            if(i != idx &amp;amp;&amp;amp; nums[i] == nums[i - 1])
                continue;
            partial.push_back(nums[i]);
            h(sol, partial, nums, i + 1);
            partial.pop_back();
        }        
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/permutations/"&gt;Permutations&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a collection of distinct integers, return all possible permutations.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [1,2,3]&lt;/li&gt;
&lt;li&gt;Output:
[  [1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
#### Solution &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very similar to the previous problem, but this time we need to consider all the elements of the array in our candidates. The way we move them around is by swapping elements at different positions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; permute(const vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        vector&amp;lt;int&amp;gt; p (nums);
        h(nums, sol, p);
        return sol;
    }
    void h(const vector&amp;lt;int&amp;gt; &amp;amp;nums, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;sol, vector&amp;lt;int&amp;gt; &amp;amp;p, int idx = 0){
        if(idx == nums.size()){
            sol.push_back(p);
            return;
        }
        for(int i = idx; i &amp;lt; nums.size(); ++i){
            swap(p[idx], p[i]);
            h(nums, sol, p, idx + 1);
            swap(p[idx], p[i]);
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/permutations-ii/"&gt;Permutations with repetitions&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a collection of numbers that might contain duplicates, return all possible unique permutations.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [1,1,2]&lt;/li&gt;
&lt;li&gt;Output:
[[1,1,2],
[1,2,1],
[2,1,1]
]&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We can apply here the same trick as before for combinations. If you could not come up with this “trick”, you can always use a set to store the solutions and then create and return an array from this set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void helper(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; res, int pos, vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        if(pos == nums.size()) {
            res.push_back(nums);
            return;
        }
        for(int i = pos; i &amp;lt; nums.size(); ++i) {
            if(i != pos &amp;amp;&amp;amp; nums[i] == nums[pos])
                continue;
            swap(nums[i], nums[pos]);
            helper(res, pos + 1, nums);
        }
        rotate(nums.begin() + pos, nums.begin() + pos + 1, nums.end());
    }

    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; permuteUnique(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        if(nums.empty())
            return {};

        sort(nums.begin(), nums.end());

        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        helper(sol, 0, nums);

        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, there is no need to learn every single data structure and algorithm in the literature to solve a vast amount of problems. &lt;em&gt;What is valuable, and can be trained, is the ability to systematically think through a problem and skills to turn your ideas into code&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;For extra practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/combination-sum/"&gt;Combination sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/combination-sum-ii/"&gt;Combination sum II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/combination-sum-iii/"&gt;Combination sum III&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Sorting and searching
&lt;/h1&gt;

&lt;h2&gt;
  
  
  7. Sorting
&lt;/h2&gt;

&lt;p&gt;Sorting is not a problem-solving technique per see but as you have seen in the previous sections we have been able to solve many problems by either sorting the input or assuming it was sorted and then applying one of the other techniques.&lt;/p&gt;

&lt;p&gt;When you are facing a new problem, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can I sort the input?&lt;/strong&gt;. For example, sometimes you have to return indices, therefore sorting is not an option&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How would this problem change if the elements were sorted?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How does sorting affect the overall complexity?&lt;/strong&gt;. The best sorting algorithms have a complexity of O(n log n) - sorting integers can be done in O(n)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, our first problem (Two sum) can be solved in linear time with the two-pointer technique because the input is sorted. However, if we have to sort, the complexity becomes O(n log n).&lt;/p&gt;

&lt;p&gt;Here you have a couple of problems that can be easily solved after sorting the input.&lt;/p&gt;

&lt;p&gt;Other solutions trade space for time, so it is worth considering them before you start writing any code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/valid-anagram/"&gt;Valid anagram&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given two strings s and t, write a function to determine if t is an anagram of s.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: s = "anagram", t = "nagaram"&lt;/li&gt;
&lt;li&gt;Output: true&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: s = "rat", t = "car"&lt;/li&gt;
&lt;li&gt;Output: false&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;By definition, two strings are anagrams if they contain &lt;strong&gt;the same characters in different order&lt;/strong&gt;. Therefore, we can simply sort both strings and compare them. The overall time complexity is O(n log n).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool isAnagram(string s, string t) {
        if(s.size() != t.size())
            return false;

        sort(s.begin(), s.end());
        sort(t.begin(), t.end());
        return  s == t;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/intersection-of-two-arrays-ii/"&gt;Intersection of two arrays&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given two arrays, write a function to compute their intersection.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: nums1 = [1,2,2,1], nums2 = [2,2]&lt;/li&gt;
&lt;li&gt;Output: [2,2]&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;You can solve this problem by sorting both arrays and using a two-pointer based approach. Give it a try before reading my solution.&lt;/p&gt;

&lt;p&gt;Imagine we have the following arrays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A = [1,2,4,5]&lt;/li&gt;
&lt;li&gt;B = [2,3,5,7,9,11]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And two pointers, &lt;em&gt;l&lt;/em&gt; for A and &lt;em&gt;r&lt;/em&gt; for B, starting at index 0 in each array.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A[l] = 1&lt;/li&gt;
&lt;li&gt;B[r] = 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to increment &lt;em&gt;l&lt;/em&gt; to see if A has a 2: B can’t contain a 1 to the right of &lt;em&gt;r&lt;/em&gt;, because it is sorted.&lt;/p&gt;

&lt;p&gt;In short, we compare both elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If they are the same, we include them to the array representing the intersection of both arrays and advance &lt;em&gt;both&lt;/em&gt; pointers&lt;/li&gt;
&lt;li&gt;If they are different, we move the pointer pointing to the smallest of the two elements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; intersect(vector&amp;lt;int&amp;gt;&amp;amp; nums1, vector&amp;lt;int&amp;gt;&amp;amp; nums2) {
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        vector&amp;lt;int&amp;gt; sol;
        int i = 0, j = 0;
        while( i &amp;lt; nums1.size() &amp;amp;&amp;amp; j &amp;lt; nums2.size()) {
            if(nums1[i] == nums2[j]) {
                sol.push_back(nums1[i]);
                ++i;
                ++j;
            } else if(nums1[i] &amp;gt; nums2[j]) {
                ++j;
            } else {
                ++i;
            }
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The time complexity of this approach is O(n log n) - even though the two-pointer part is linear - and the space complexity is O(1) - not including the space needed to store the intersection, of course, in which case we could say it is O(min(length(A), length(B)).&lt;/p&gt;

&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://leetcode.com/problems/k-closest-points-to-origin/"&gt;K closest points to origin&lt;/a&gt;. In another section, I will present a different solution, slightly faster.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/largest-number/"&gt;Largest number&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Intervals
&lt;/h2&gt;

&lt;p&gt;Most interval related problems I have seen boil down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modeling the interval&lt;/strong&gt; as an array of two elements, a pair/tuple or a custom class (this is the cleanest option)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sorting&lt;/strong&gt; the input&lt;/li&gt;
&lt;li&gt;Iterating through the sorted array and deciding what to do based on the starts/ends of the intervals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see this as yet another type of problem that can be simplified after sorting the input, which is why I have included it in this section.&lt;/p&gt;

&lt;p&gt;I’m leaving here my solution to two exercises, based on what I have just described. Try them before reading my solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/merge-intervals/"&gt;Merge intervals&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a collection of intervals, merge all overlapping intervals.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: intervals = [[1,3],[2,6],[8,10],[15,18]]&lt;/li&gt;
&lt;li&gt;Output: [[1,6],[8,10],[15,18]]&lt;/li&gt;
&lt;li&gt;Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; merge(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; intervals) {
        sort(intervals.begin(), intervals.end(), [](const auto&amp;amp; i1, const auto&amp;amp; i2){
           return i1[0] &amp;lt; i2[0];
        });
        int i = 0;
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        vector&amp;lt;int&amp;gt; curr(2);
        while(i &amp;lt; intervals.size()){
            curr = intervals[i++];
            while(i &amp;lt; intervals.size() &amp;amp;&amp;amp; intervals[i][0] &amp;lt;= curr[1]){
                curr[1] = max(curr[1], intervals[i][1]);
                ++i;
            }
            sol.push_back(curr);
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://leetcode.com/problems/interval-list-intersections/"&gt;Interval list intersections&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given two lists of closed intervals, each list of intervals is pairwise disjoint and in &lt;strong&gt;sorted order&lt;/strong&gt;. Return the intersection of these two interval lists.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; intervalIntersection(const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; A, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; B) {
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
    int i = 0, j = 0;

    while(i &amp;lt; A.size() &amp;amp;&amp;amp; j &amp;lt; B.size()){
        const int lo = max(A[i][0], B[j][0]);
        const int hi = min(A[i][1], B[j][1]);
        if(lo &amp;lt;= hi){
            sol.push_back({lo, hi});
        }
        if(A[i][1] &amp;lt; B[j][1])
            ++i;
        else
            ++j;
    }
    return sol;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Variations on &lt;a href="https://en.wikipedia.org/wiki/Binary_search_algorithm"&gt;binary search&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Binary search&lt;/em&gt; is a search algorithm that can be applied to sorted data structures (like arrays or binary search trees) with O(log n) time complexity and O(1) space complexity. &lt;/p&gt;

&lt;p&gt;What you might not know is its implementation’s most common bug. Assuming we are performing a binary search in the elements whose range goes from [l,r], the element in the middle is usually computed as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const int m = (l + r) / 2;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Can you spot the problem here?&lt;/p&gt;

&lt;p&gt;This line can overflow. The safe way of computing this middle element is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const int m = l + (r - l) / 2;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here’s a basic implementation of binary search, using C++ templates. If you understand how it works and how to implement it correctly, you can solve many problems that just have a little tweak in the requirements or that are &lt;em&gt;binary search&lt;/em&gt; problems in disguise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template&amp;lt;typename T&amp;gt;
int binary_search(const vector&amp;lt;T&amp;gt;&amp;amp; v, int k) {
    int l = 0, r = v.size() - 1;
    while(l&amp;lt;=r) {
     const int m = l + (r - l) / 2;
     if(k == v[m]) {
         return m;
     } else if (k &amp;gt; v[m]) {
         l = m + 1;
     } else {
         r = m - 1;
     }
    }
    return -1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/sqrtx/"&gt;Integer square root&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Compute and return the square root of x, where x is guaranteed to be a non-negative integer.&lt;br&gt;
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 4&lt;/li&gt;
&lt;li&gt;Output: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We need to find a number in the range [0, x], which is sorted. It sounds a lot like a binary search problem.&lt;/p&gt;

&lt;p&gt;It is not critical to know this, but we can optimize a little:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;em&gt;x&lt;/em&gt; is 0 or 1, its square root is &lt;em&gt;x&lt;/em&gt;. This lets us start testing numbers from 2.&lt;/li&gt;
&lt;li&gt;The upper bound of the range can be reduced to x/2, since (x/2)^2 = x^2/4 &amp;gt;= x =&amp;gt; x &amp;gt;= 4, which is true for any integer in the range [2,…]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, we can search in [2, x/2] and speed things up a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int mySqrt(int x) {
        if(x == 0 || x == 1)
            return x;
        int sol = 1;
        int l = 2, r = x / 2;
        while(l &amp;lt;= r){
            const long m = l + (r - l) / 2;
            if(m * m == x)
                return m;
            else if(m * m &amp;gt; x){
                r = m - 1;
            } else {
                sol = m;
                l = m + 1;
            }
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/search-insert-position/"&gt;Search insert position&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/random-pick-with-weight/"&gt;Random pick with weight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/"&gt;Minimum in rotated sorted array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/"&gt;Minimum in rotated sorted array 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. &lt;a href="https://en.wikipedia.org/wiki/bfs"&gt;Breadth-First Search&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is one of the techniques you need to know to explore trees and graphs. Since many problems can be modeled as graphs, you &lt;strong&gt;must know&lt;/strong&gt; this technique. To implement it, we just need to use a queue &lt;em&gt;q&lt;/em&gt; and add to this same queue the children of the nodes we process from &lt;em&gt;q&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;At any given point in the iteration, BFS visits all the nodes at the same distance from the origin. This will become clearer after some of these examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/word-ladder/"&gt;Word ladder&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given two words (beginWord and endWord), and a dictionary's word list, find the length of the shortest transformation sequence from beginWord to endWord, such that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one letter can be changed at a time.&lt;/li&gt;
&lt;li&gt;Each transformed word must exist in the word list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return 0 if there is no such transformation sequence.&lt;/li&gt;
&lt;li&gt;All words have the same length.&lt;/li&gt;
&lt;li&gt;All words contain only lowercase alphabetic characters.&lt;/li&gt;
&lt;li&gt;You may assume no duplicates in the word list.&lt;/li&gt;
&lt;li&gt;You may assume beginWord and endWord are non-empty and are not the same.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input:&lt;/li&gt;
&lt;li&gt;beginWord = "hit",&lt;/li&gt;
&lt;li&gt;endWord = "cog",&lt;/li&gt;
&lt;li&gt;wordList = ["hot","dot","dog","lot","log","cog"]&lt;/li&gt;
&lt;li&gt;Output: 5&lt;/li&gt;
&lt;li&gt;Explanation: As one shortest transformation is "hit" -&amp;gt; "hot" -&amp;gt; "dot" -&amp;gt; "dog" -&amp;gt; "cog",
return its length 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;I got asked this question during my on-site interview at Amazon. The idea is to model this problem using a graph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes represent words&lt;/li&gt;
&lt;li&gt;Edges connect words that only differ by one letter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup, this problem is equivalent to finding a path between two nodes in a graph, which BFS can solve. Since all edges have the same weight (1), we do not need Dijkstra or any other fancier algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int ladderLength(const string &amp;amp;beginWord, const string &amp;amp;endWord, const vector&amp;lt;string&amp;gt;&amp;amp; wordList) {
        if(beginWord == endWord)
            return 1;
        unordered_set&amp;lt;string&amp;gt; dict(wordList.begin(), wordList.end());
        queue&amp;lt;string&amp;gt; todo;
        todo.push(beginWord);
        dict.erase(beginWord);
        int ladder = 1;
        while (!todo.empty()) {
            ladder++;
            int n = todo.size();
            for (int i = 0; i &amp;lt; n; i++) {
                string word = todo.front();
                todo.pop();
                for (int j = 0; j &amp;lt; word.size(); j++) {
                    char c = word[j];
                    for (int k = 0; k &amp;lt; 26; k++) {
                        word[j] = 'a' + k;
                        if (dict.find(word) != dict.end()) {
                            if (word == endWord) {
                                return ladder;
                            }
                            todo.push(word);
                            dict.erase(word);
                        }
                     }
                    word[j] = c;
                }
            }
        }
        return 0;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;After you visit the DFS section&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;What would happen if we use DFS instead? Do you see any benefits/drawbacks?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/binary-tree-level-order-traversal/"&gt;Order level tree traversal&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).&lt;/p&gt;

&lt;p&gt;Open the link for a graphical description of the problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;You only need to add here a little tweak to the standard BFS algorithm: you need to know how many elements in the queue you need to process for each level.&lt;/p&gt;

&lt;p&gt;This is one approach that can be applied to many other problems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; levelOrder(TreeNode* root) {
        if(!root)
            return {};
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;
        queue&amp;lt;TreeNode*&amp;gt; q;
        q.push(root);
        vector&amp;lt;int&amp;gt; partial;
        while(!q.empty()){
            int size = q.size();
            while(size--&amp;gt;0){
                auto n = q.front();
                partial.push_back({n-&amp;gt;val});
                q.pop();
                if(n-&amp;gt;left)
                    q.push({n-&amp;gt;left});
                if(n-&amp;gt;right)
                    q.push({n-&amp;gt;right});
            }
            sol.push_back(partial);
            partial.clear();
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Let me propose a different kind of challenge: building something, instead of solving abstract problems. I find it more fun and you can add them to your Github profile. Here are just two examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Web_crawler"&gt;Web crawler&lt;/a&gt; using BFS to explore all the links on a website.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Minesweeper_(video_game)"&gt;Minesweeper&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. &lt;a href="https://en.wikipedia.org/wiki/Depth-first_search"&gt;Depth-First Search&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Similar to BFS in its purpose: explore trees and graphs. DFS is not guaranteed to find the shortest path between two points, but it will find any existing path.&lt;/p&gt;

&lt;p&gt;It is usually shorter to implement than BFS. Some people find it easier. Others, because of the recursive calls, not so much. It is up to you. Just make sure you think about potential stack overflow issues if the size of the stack starts to get big.&lt;/p&gt;

&lt;p&gt;Some problems are much easier to be solved with DFS/recursion, that it is worth practicing.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/number-of-islands/"&gt;Number of islands&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]]&lt;/li&gt;
&lt;li&gt;Output: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;I got this problem at my first phone interview at Amazon.&lt;/p&gt;

&lt;p&gt;As soon as you see a matrix, think of a graph. This problem (and its variations) is very straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Iterate through the matrix&lt;/li&gt;
&lt;li&gt;For every 1 you find, increase the counter and &lt;em&gt;sink&lt;/em&gt; the island&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To sink the island, you need to visit all the surrounding 1s in the matrix, which is equivalent to &lt;a href="https://en.wikipedia.org/wiki/Component_(graph_theory)"&gt;visit all the neighbors of that node and of all its neighbors&lt;/a&gt;, which sounds a lot like a recursive problem.&lt;/p&gt;

&lt;p&gt;You can try to solve this using BFS too, but DFS is much shorter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int numIslands(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; grid) {
        int numIslands = 0;
        for(int r = 0; r &amp;lt; grid.size(); ++r){
            for(int c = 0; c &amp;lt; grid[0].size(); ++c){
                if(grid[r][c] == '1'){
                    ++numIslands;
                    sinkIslands(grid, r, c);
                }
            }
        }
        return numIslands;
    }

    const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; dirs {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    void sinkIslands(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt; &amp;amp;m, int r, int c){
        m[r][c] = '0';
        for(const auto &amp;amp;d : dirs){
            const int nr = r + d[0];
            const int nc = c + d[1];
            if(isValid(m, nr, nc)){
                sinkIslands(m, nr, nc);
            }
        }
    }

    bool isValid(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt; &amp;amp;m, int r, int c){
        return r &amp;gt;= 0 &amp;amp;&amp;amp; r &amp;lt; m.size() &amp;amp;&amp;amp; c &amp;gt;= 0 &amp;amp;&amp;amp; c &amp;lt; m[0].size() &amp;amp;&amp;amp; m[r][c] == '1';
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/symmetric-tree/"&gt;Symmetric tree&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Many tree-related problems have relatively straightforward recursive solutions. This problem could be solved using BFS but DFS makes it so much easier.&lt;/p&gt;

&lt;p&gt;I will leave this one here as an exercise for you. Just use my solution in case you get stuck.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool isSymmetric(TreeNode* root) {
        if(!root)        
            return true;
        return helper(root-&amp;gt;left, root-&amp;gt;right);
    }
    bool helper(TreeNode* p, TreeNode* q){
        if(!p &amp;amp;&amp;amp; !q)
            return true;
        if(!p || !q)
            return false;
        return p-&amp;gt;val == q-&amp;gt;val &amp;amp;&amp;amp; iS(p-&amp;gt;left, q-&amp;gt;right) &amp;amp;&amp;amp; iS(p-&amp;gt;right, q-&amp;gt;left);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenges
&lt;/h3&gt;

&lt;p&gt;Take the same challenges and exercises I gave you for BFS and try to implement them using DFS instead. Also, for more practice, give a try to the following exercises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/path-sum/"&gt;Path sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/path-sum-ii/"&gt;Path sum 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/validate-binary-search-tree/"&gt;Validate BST&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. &lt;a href="https://en.wikipedia.org/wiki/Topological_sorting#:~:text=In%20computer%20science%2C%20a%20topological,before%20v%20in%20the%20ordering."&gt;Topological sort&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can see this algorithm as an application of DFS. Its implementation just needs one minor change to the regular DFS: after processing all the children of a node, add this node to a stack.&lt;/p&gt;

&lt;p&gt;It is that simple.&lt;/p&gt;

&lt;p&gt;The best way to intuitively understand what this algorithm achieves is to imagine a bunch of tasks, some of which depend on others (task 1 cannot start until task 2 has finished). A topological sort will list all these tasks preserving this structure of dependencies.&lt;/p&gt;

&lt;p&gt;Let's solve a problem using this algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/course-schedule-ii/"&gt;Course schedule II&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have prerequisites, for example, to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]&lt;/p&gt;

&lt;p&gt;Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses. There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 2, [[1,0]] &lt;/li&gt;
&lt;li&gt;Output: [0,1]&lt;/li&gt;
&lt;li&gt;Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 4, [[1,0],[2,0],[3,1],[3,2]]&lt;/li&gt;
&lt;li&gt;Output: [0,1,2,3] or [0,2,1,3]&lt;/li&gt;
&lt;li&gt;Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3].&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This is the classical topological sort problem. There are a bunch of courses to take and some depend on others. This can be modeled as a directed graph. A topological sort would return &lt;em&gt;the ordering of courses you should take to finish all courses&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A prerequisite to applying topological sort is that the graph is &lt;strong&gt;directed and acyclic&lt;/strong&gt;.  From the problem description, we can see that the graph is directed. We can detect if it contains any cycles &lt;em&gt;and&lt;/em&gt; compute a topological sort in the same pass.&lt;/p&gt;

&lt;p&gt;A more indirect but still valid approach would be to first check whether it has cycles and only if there are no cycles, compute a topological sort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; findOrder(int numCourses, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; prerequisites) {
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; adj(numCourses, vector&amp;lt;int&amp;gt;(0));

        for(const auto &amp;amp;p : prerequisites){
            int u = p[0];
            int v = p[1];
            adj[u].push_back(v);
        }

        vector&amp;lt;bool&amp;gt; white(numCourses, true),
                     grey(numCourses), 
                     black(numCourses);
        vector&amp;lt;int&amp;gt; sol (0);        
        for(int i = 0; i &amp;lt; numCourses; ++i){
            if(white[i] &amp;amp;&amp;amp; hasCycle(adj, i, white, grey, black, sol)){
                return {};
            }
        }
        return sol;
}

    bool hasCycle(const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; adj, int i, vector&amp;lt;bool&amp;gt; &amp;amp;white, vector&amp;lt;bool&amp;gt; &amp;amp;grey, vector&amp;lt;bool&amp;gt; &amp;amp;black, vector&amp;lt;int&amp;gt;&amp;amp; sol){
        //We have started exploring this node
        white[i] = false;
        grey[i] = true;

        for(const auto &amp;amp; n : adj[i]){
            if(black[i])
                continue;
            if(grey[n] || hasCycle(adj, n, white, grey, black, sol))
                return true;
        }

        grey[i] = false;
        black[i] = true;
        sol.push_back(i);
        return false;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.hackerearth.com/de/practice/algorithms/graphs/topological-sort/practice-problems/"&gt;Here&lt;/a&gt; you can find a few more problems to practice.&lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

&lt;h1&gt;
  
  
  Extending basic data structures
&lt;/h1&gt;

&lt;h2&gt;
  
  
  13. Dequeues
&lt;/h2&gt;

&lt;p&gt;I have seen data structure mostly used as another way to implement the sliding window technique you read about earlier in this article. The only difference with a standard FIFO queue is that you can operate (insert and delete elements) on &lt;strong&gt;both ends&lt;/strong&gt; of the queue.&lt;/p&gt;

&lt;p&gt;That’s it. Simple.&lt;/p&gt;

&lt;p&gt;Let's see how such a minor change can simplify some kind of these problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/sliding-window-maximum/"&gt;Sliding window maximum&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array, nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.&lt;/p&gt;

&lt;p&gt;*Note: Open the link for a better understanding of the problem (there is an image). *&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3&lt;/li&gt;
&lt;li&gt;Output: [3,3,5,5,6,7] &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We will use the dequeue to store &lt;em&gt;indices&lt;/em&gt;, not values. We need this to know what elements are still part of the sliding window. For every iteration, there are four things to do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove elements in the dequeue which are outside of the current sliding window (one per iteration)&lt;/li&gt;
&lt;li&gt;Remove &lt;strong&gt;all&lt;/strong&gt; elements in the dequeue which are smaller than the current element we are at since they cannot represent the max of that sliding window&lt;/li&gt;
&lt;li&gt;Add the current element to the deque&lt;/li&gt;
&lt;li&gt;Once we have completed the first sliding window, we can start adding elements to our solution. By design, the element at the front of our dequeue will contain the maximum of the sliding window, which is what we are interested in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This technique can be applied to find the minimum or other properties of a contiguous block of data in an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; maxSlidingWindow(const vector&amp;lt;int&amp;gt;&amp;amp; nums, int k) {
    vector&amp;lt;int&amp;gt; sol;

    deque&amp;lt;int&amp;gt; dq;
    for (int i=0; i&amp;lt;nums.size(); i++) {
        // Step 1
        if (!dq.empty() &amp;amp;&amp;amp; dq.front() == i-k) 
            dq.pop_front();

        // Step 2
        while (!dq.empty() &amp;amp;&amp;amp; nums[dq.back()] &amp;lt; nums[i])
            dq.pop_back();

        // Step 3
        dq.push_back(i);

        // Step 4
        if (i &amp;gt;= k-1) 
            sol.push_back(nums[dq.front()]);
    }
    return sol;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge
&lt;/h3&gt;

&lt;p&gt;Design your own &lt;a href="https://leetcode.com/problems/design-circular-deque/"&gt;circular dequeue&lt;/a&gt;, to fully grasp the internals of this data structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. &lt;a href="https://en.wikipedia.org/wiki/Trie"&gt;Trie&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The best way to think of a trie is as an extension of a tree, where you store characters that form words as you move through the different branches of the trie.&lt;/p&gt;

&lt;p&gt;There are variants where you store suffixes instead of prefixes, where you use compression to reduce the size of the trie, etc. But at its basic, it is another type of tree.&lt;/p&gt;

&lt;p&gt;They are used everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-complete&lt;/li&gt;
&lt;li&gt;Spell checkers&lt;/li&gt;
&lt;li&gt;IP routing&lt;/li&gt;
&lt;li&gt;Longest prefix/suffix matching&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/implement-trie-prefix-tree/"&gt;Implement a trie&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Implement a trie with insert, search, and startsWith methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Here is a simple implementation (for an interview, of course) of a trie. Compared to a tree, you just:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An extra boolean to indicate whether that node marks the end of a word&lt;/li&gt;
&lt;li&gt;A data structure to store pointers to the node’s children: a hash table, an array of characters, etc.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Trie {
private:
    struct Node{
        bool isWord;
        unordered_map&amp;lt;int, Node*&amp;gt; children;
        Node() : isWord(false) {}
    };

    Node* findNode(const string &amp;amp;word){
        Node* curr = root;
        for(int i = 0; i &amp;lt; word.size() &amp;amp;&amp;amp; curr; ++i)
            curr = curr-&amp;gt;children[word[i] - 'a'];
        return curr;
    }

public:
    Node* root;
    /** Initialize your data structure here. */
    Trie() {
        root = new Node();
    }

    /** Inserts a word into the trie. */
    void insert(const string &amp;amp;word) {
        Node * curr = root;
        for(int i = 0; i &amp;lt; word.size(); ++i){
            const char c = word[i] - 'a';
            if(!curr-&amp;gt;children[c]){
                Node* newChild = new Node();
                curr-&amp;gt;children[c] = newChild;
            } 
                curr = curr-&amp;gt;children[c];
        }
        curr-&amp;gt;isWord = true;
    }

    /** Returns true if the word is in the trie. */
    bool search(const string &amp;amp;word) {
        Node* curr = findNode(word);
        return curr ? curr-&amp;gt;isWord : false;
    }

    /** Returns true if there is any word in the trie that starts with the given prefix. */
    bool startsWith(const string &amp;amp;prefix) {
        Node* curr = findNode(prefix);
        return curr ? true : false;
    }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/word-search-ii/"&gt;Word search II&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a 2D board and a list of words from the dictionary, find all words on the board. Each word must be constructed from letters of adjacent cells, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 
board = [
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
words = ["oath","pea","eat","rain"]&lt;/li&gt;
&lt;li&gt;Output: ["eat","oath"]&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This might not be the simplest way of solving this problem, but it is a clear application of a trie. &lt;/p&gt;

&lt;p&gt;At every step, you will have built some candidate string and need to check if it belongs to the dictionary. A hash set containing all the words in the dictionary would give a very good performance. Why bothering with a trie then? Because a trie can tell you whether that path is worth exploring or not, improving the efficiency of our solution.&lt;/p&gt;

&lt;p&gt;In our previous example, imagine we form the string “oa”. &lt;/p&gt;

&lt;p&gt;We can check if this prefix (potential word) exists in our trie. It exists since we have added the word “oath”. Now imagine we keep moving right through our board and form the string “oaa”. &lt;/p&gt;

&lt;p&gt;In our trie, there are no words that contain the prefix “oaa”, so we can &lt;strong&gt;backtrack&lt;/strong&gt; at this point.&lt;/p&gt;

&lt;p&gt;With a hash set that contains all the words, you could not do this type of prefix matching, unless you create two different tables: one for prefixes and another one for words.&lt;/p&gt;

&lt;p&gt;This is a complex problem because it combines different elements and it is not easy to implement, so do not get discouraged if it takes you a few tries (no pun intended) to get it right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; dirs {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    struct Trie{
        struct Node{
            bool isWord;
            unordered_map&amp;lt;char, Node*&amp;gt; children;
            Node() : isWord(false){}
        };

        Node* root;

        Trie(){root = new Node();}

        void insert (const string&amp;amp; w){
            Node* cur = root;
            for(const auto &amp;amp;c : w){
                if(cur-&amp;gt;children.find(c) == cur-&amp;gt;children.end()){
                    cur-&amp;gt;children[c] = new Node();
                }
                cur = cur-&amp;gt;children[c];
            }
            cur-&amp;gt;isWord = true;
        }

        bool hasPrefix(const string &amp;amp;prefix){
            Node* cur = root;
            for(const auto &amp;amp;c : prefix){
                if(cur-&amp;gt;children.find(c) == cur-&amp;gt;children.end()){
                    return false;
                }
                cur = cur-&amp;gt;children[c];
            }
            lastNode = cur;
            return cur != nullptr;
        }

        bool isValidWord(const string &amp;amp;w){
            if(lastNode){
                bool res = lastNode-&amp;gt;isWord;
                return res;
            }
            Node* cur = root;
            for(const auto &amp;amp;c : w){
                cur = cur-&amp;gt;children[c];
                if(!cur){
                    return false;
                }
            }
            lastNode = cur;
            return lastNode-&amp;gt;isWord;
        }

        void deleteWord(){
            lastNode-&amp;gt;isWord = false;
            lastNode = nullptr;
        }
        Node* lastNode;
    };    

    Trie t;
public:
    vector&amp;lt;string&amp;gt; findWords(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board, const vector&amp;lt;string&amp;gt;&amp;amp; words) {
        for(const auto&amp;amp; w : words)
            t.insert(w);

        vector&amp;lt;string&amp;gt; sol;
        for(int row = 0; row &amp;lt; board.size(); ++row){
            for(int col = 0; col &amp;lt; board[0].size(); ++col){
                string candidate (1, board[row][col]);
                if(t.hasPrefix(candidate))
                    addWords(board, row, col, sol, candidate);
            }
        }
        return sol;
    }

    void addWords(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt; &amp;amp;board, int row, int col, vector&amp;lt;string&amp;gt; &amp;amp;sol, string &amp;amp;candidate){
        if(t.isValidWord(candidate)){
            sol.push_back(candidate);
            t.deleteWord();
        }

        const char old = board[row][col];
        board[row][col] = '-';
        for(const auto &amp;amp;d : dirs){
            const int nrow = row + d[0];
            const int ncol = col + d[1];
            if(nrow &amp;gt;= 0 &amp;amp;&amp;amp; nrow &amp;lt; board.size() 
                &amp;amp;&amp;amp; ncol &amp;gt;= 0 &amp;amp;&amp;amp; ncol &amp;lt; board[0].size() 
                    &amp;amp;&amp;amp; board[nrow][ncol] != '.' 
                        &amp;amp;&amp;amp; t.hasPrefix(candidate + board[nrow][ncol])){
                candidate.push_back(board[nrow][ncol]);
                addWords(board, nrow, ncol, sol, candidate);
                candidate.pop_back();
            }
        }
        board[row][col] = old;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;Design your own &lt;a href="https://en.wikipedia.org/wiki/Autocomplete"&gt;autocomplete&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Two instances of the same data structure
&lt;/h2&gt;

&lt;p&gt;Some problems can be solved by using two different instances of the same data structure, so it is worth keeping it in mind when you get stuck in a problem. I have seen it mostly with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queues&lt;/li&gt;
&lt;li&gt;Stacks&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not limit yourself to these.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/find-median-from-data-stream/"&gt;Find median from a stream of data&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle values.&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[2,3,4], the median is 3&lt;/li&gt;
&lt;li&gt;[2,3], the median is (2 + 3) / 2 = 2.5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Design a data structure that supports the following two operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;void addNum(int num) - Add an integer number from the data stream to the data structure.&lt;/li&gt;
&lt;li&gt;double findMedian() - Return the median of all elements so far.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MedianFinder {
    priority_queue&amp;lt;int, vector&amp;lt;int&amp;gt;, less&amp;lt;int&amp;gt;&amp;gt; L;
    priority_queue&amp;lt;int, vector&amp;lt;int&amp;gt;, greater&amp;lt;int&amp;gt;&amp;gt; H;    
public:

    MedianFinder() { }

    void addNum(int x) {
        if(L.empty() == false &amp;amp;&amp;amp; x &amp;gt; L.top()) {
            H.emplace(x);
        } else {
            L.emplace(x);
        }

        if(H.size() &amp;gt; L.size() + 1) {
            L.emplace(H.top());
            H.pop();
        } else if(L.size() &amp;gt; H.size() + 1) {
            H.emplace(L.top());
            L.pop();
        }
    }

    double findMedian() {
        if(H.size() == L.size()) {
            return (H.top() + L.top()) * 0.5;
        } else {
            return H.size() &amp;gt; L.size() ? H.top() : L.top();
        }
    }

};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;In increasing order of difficulty: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/implement-queue-using-stacks/"&gt;Implement a queue using two stacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/"&gt;Tree zigzag order traversal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/find-median-from-data-stream"&gt;Media from data stream&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Miscellanea
&lt;/h1&gt;

&lt;h2&gt;
  
  
  16. &lt;a href="https://en.wikipedia.org/wiki/Bitwise_operation"&gt;Bit manipulation&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This section deserves a separate article. Here I will list some basic &lt;em&gt;tricks&lt;/em&gt; and common bit manipulation problems.&lt;/p&gt;

&lt;p&gt;This is &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html"&gt;the most comprehensive site&lt;/a&gt; I have found on this topic. Use it as a reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/missing-number/"&gt;Missing number&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: [3,0,1]&lt;/li&gt;
&lt;li&gt;Output: 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This problem can be solved just by using the XOR operator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any bit XORed with itself produces a 0 -&amp;gt; a ^ a = 0&lt;/li&gt;
&lt;li&gt;Any bit XORed with 0 produces the original bit -&amp;gt; a ^ 0 = a&lt;/li&gt;
&lt;li&gt;XOR is associative = a ^ (b ^ c) = (a ^ b ) ^ c&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we XOR all the numbers in the array (integers in the range [0,n]) with all the integers in [0 to n], the pairs will produce &lt;em&gt;zeroes&lt;/em&gt; and the missing number will be XORed with 0 (resulting in itself), solving our problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int missingNumber(const vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        int res = nums.size();
        for(int i = 0; i &amp;lt; nums.size(); ++i)
            res ^= (i ^ nums[i]);
        return res;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/power-of-two/"&gt;Power of two&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an integer, write a function to determine if it is a power of two.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;I got this one in an interview.&lt;/p&gt;

&lt;p&gt;Powers of two can be expressed in binary as a leading 1 and some 0s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2: 1&lt;/li&gt;
&lt;li&gt;4: 10&lt;/li&gt;
&lt;li&gt;8: 100&lt;/li&gt;
&lt;li&gt;16: 1000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, it is simple to figure out if a number is a power of two or not. You can achieve fast if you know what the following line does (I am sure you can figure it out on your own):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x &amp;amp; (x-1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This trick is worth knowing since it is used a lot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool isPowerOfTwo(int n) {
        return n &amp;gt; 0 ? (n &amp;amp; (n - 1)) == 0 : false;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/number-of-1-bits/"&gt;Number of 1s&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight).&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 00000000000000000000000000001011&lt;/li&gt;
&lt;li&gt;Output: 3&lt;/li&gt;
&lt;li&gt;Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This problem is very straightforward: iterate through all the bits in the input and count how many how of them are 1s. &lt;/p&gt;

&lt;p&gt;Try to use the trick I showed you in the previous exercise to improve the performance of this algorithm (in the average case).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int hammingWeight(uint32_t n) {
        int sum = 0;
        while (n != 0) {
            sum++;
            n &amp;amp;= (n - 1);
        }
        return sum;  
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Challenges
&lt;/h4&gt;

&lt;p&gt;These are for you to practice the previous techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/single-number/"&gt;Single number&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/gray-code/"&gt;Gray code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/hamming-distance/"&gt;Hamming distance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/problems/power-of-four/"&gt;Power of 4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  17. Top 'K' Elements
&lt;/h2&gt;

&lt;p&gt;This is another very frequent type of problem. You are given a list of elements and have to return the top K, defining &lt;em&gt;top&lt;/em&gt; as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The largest/smallest&lt;/li&gt;
&lt;li&gt;The closest/furthest to a point&lt;/li&gt;
&lt;li&gt;The most frequent in the list&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have seen some of the following (or some sort of variation) asked in interviews.&lt;/p&gt;

&lt;p&gt;There is no single data structure that will always give the right solution, but the following elements are very useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hash table&lt;/li&gt;
&lt;li&gt;Priority queue&lt;/li&gt;
&lt;li&gt;Sorting (the input or as an intermediate step)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Priority queues usually provide a better complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/top-k-frequent-words/"&gt;Top k frequent words&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2&lt;/li&gt;
&lt;li&gt;Output: ["i", "love"]&lt;/li&gt;
&lt;li&gt;Explanation: "i" and "love" are the two most frequent words. Note that "i" comes before "love" due to a lower alphabetical order.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Pretty straightforward: count how many times each word appears (using a hash table) and &lt;em&gt;somehow&lt;/em&gt; return the k most common elements.&lt;/p&gt;

&lt;p&gt;For this last part, you either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put all the elements with its frequencies in an array and sort it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a priority queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is worth knowing this second approach since it can be applied to other problems.&lt;/p&gt;

&lt;p&gt;Here is a simple solution in C++ using a priority queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vector&amp;lt;string&amp;gt; topKFrequent(const vector&amp;lt;string&amp;gt;&amp;amp; words, int k) {
        map&amp;lt;string, int&amp;gt; freq;
        for(const auto &amp;amp;w : words)
            freq[w]++;

        auto l = [](const pair&amp;lt;int, string&amp;gt; &amp;amp; p1, const pair&amp;lt;int, string&amp;gt; &amp;amp;p2){
            if(p1.first == p2.first)
                return p1.second &amp;lt; p2.second;
            else
                return p1.first &amp;gt; p2.first;
        };
        priority_queue&amp;lt;pair&amp;lt;int, string&amp;gt;, vector&amp;lt;pair&amp;lt;int, string&amp;gt;&amp;gt;, decltype(l)&amp;gt; pq(l);

        for(auto it = freq.begin(); it != freq.end(); ++it){
            if(pq.size() &amp;lt; k){
                pq.push({it-&amp;gt;second, it-&amp;gt;first});
            } else {
                auto top = pq.top();
                if(top.first &amp;lt; it-&amp;gt;second){
                    pq.pop();
                    pq.push({it-&amp;gt;second, it-&amp;gt;first});
                }
            }
        }
        vector&amp;lt;string&amp;gt; sol (k);
        while(!pq.empty()){
            sol[--k] = pq.top().second;
            pq.pop();
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://leetcode.com/problems/top-k-frequent-elements/"&gt;Variation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/k-closest-points-to-origin/"&gt;K closest points to origin&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We have a list of points on the plane. Find the K closest points to the origin (0, 0). Here, the distance between two points on a plane is the Euclidean distance.&lt;/p&gt;

&lt;p&gt;You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: points = [[1,3],[-2,2]], K = 1&lt;/li&gt;
&lt;li&gt;Output: [[-2,2]]&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The obvious solution is to compute the distance to every single point, add them to an array, sort and get the top k. This is fine, but it can be improved with a priority queue.&lt;/p&gt;

&lt;p&gt;We use a &lt;em&gt;max heap&lt;/em&gt;, where the root of the heap is the maximum element of the heap. Why the maximum? Our heap contains the K points closest to the origin and the root points to the element that is the furthest from the origin amongst all the other points. If we find a point closer to this one, it may still be further than the rest, but we need to drop our current top and add this new point to the heap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typedef pair&amp;lt;int, vector&amp;lt;int&amp;gt;&amp;gt; pivi;
public:
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; kClosest(const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; points, int K) {

        auto l = [] (const pivi&amp;amp; p1, const pivi &amp;amp;p2) {
            return p1.first &amp;lt; p2.first;
        };

        priority_queue&amp;lt;pivi, vector&amp;lt;pivi&amp;gt;, decltype(l)&amp;gt; pq(l);

        for(const auto &amp;amp;p : points){
            //Avoid taking the square root. Won’t change the result and it’s faster
            const int d = p[0] * p[0] + p[1] * p[1];

            if(pq.size() &amp;lt; K)
                pq.push({d, {p[0], p[1]}});
            else if(pq.top().first &amp;gt; d){
                pq.pop();
                pq.push({d, {p[0], p[1]}});
            }
        }

        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; sol;

        for(int i = 1; i &amp;lt;= K; ++i){
            sol.push_back(pq.top().second);
            pq.pop();
        }
        return sol;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  18. K-way merge
&lt;/h2&gt;

&lt;p&gt;These problems are common too. There is not a unique approach to all of them, but if you know how to solve the problem of merging 2 lists, you can solve the problem of merging K lists to a bunch of instances of the simpler problem. As I mentioned, this is a very powerful approach that you should always keep in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/merge-two-sorted-lists/"&gt;Merge 2 sorted lists&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists.&lt;br&gt;
Example:&lt;br&gt;
Input: 1-&amp;gt;2-&amp;gt;4, 1-&amp;gt;3-&amp;gt;4Output: 1-&amp;gt;1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;4&lt;/p&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We solve this problem with the same Two pointer technique we saw at the beginning of this article. In this case, we traverse linked lists instead of arrays, but the same ideas apply.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    ListNode dh(1), *curr = &amp;amp;dh;
    while(l1 &amp;amp;&amp;amp; l2){
        if(l1-&amp;gt;val &amp;lt;= l2-&amp;gt;val) {
            curr-&amp;gt;next = l1;
            l1 = l1-&amp;gt;next;
        } else {
            curr-&amp;gt;next = l2;
            l2 = l2-&amp;gt;next;
        }
        curr = curr-&amp;gt;next;
    }
    if(l1){
        curr-&amp;gt;next = l1;
    } else if(l2) {
        curr-&amp;gt;next = l2;
    }

    return dh.next;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/merge-k-sorted-lists/"&gt;Merge k sorted lists&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given an array of linked-lists lists, each linked list is sorted in ascending order.&lt;/p&gt;

&lt;p&gt;Merge all the linked-lists into one sort linked-list and return it.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;p&gt;Input: lists = [[1,4,5],[1,3,4],[2,6]]&lt;br&gt;
Output: [1,1,2,3,4,4,5,6]&lt;br&gt;
Explanation: The linked-lists are:&lt;br&gt;
[&lt;br&gt;
  1-&amp;gt;4-&amp;gt;5,&lt;br&gt;
  1-&amp;gt;3-&amp;gt;4,&lt;br&gt;
  2-&amp;gt;6&lt;br&gt;
]&lt;br&gt;
merging them into one sorted list:&lt;br&gt;
1-&amp;gt;1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;4-&amp;gt;5-&amp;gt;6&lt;/p&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;This is the general version of the previous problem. As I said, you can reduce this problem to many instances of the previous problem by merging lists 2 at a time. However, here I will present a more efficient solution.&lt;/p&gt;

&lt;p&gt;Now, instead of two sorted lists, we have K. We need to create a list from picking the next minimum element of all the lists. Since they are sorted, it will be the first element of one of these lists. Luckily, there is a data structure that returns its minimum element in O(1) and has an insertion complexity of O(log K): a priority queue.&lt;/p&gt;

&lt;p&gt;For every list, we add to the priority queue a pair containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The head of that list &lt;/li&gt;
&lt;li&gt;An index to remember to which list that element belongs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After we pop an element, we add its value to our solution and add to the priority queue the new head of that list (the pair stores the value and the index of the list).&lt;/p&gt;

&lt;p&gt;With this information, try to solve the problem. You will learn much more from it than from reading my solution without trying first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ListNode* mergeKLists(vector&amp;lt;ListNode*&amp;gt;&amp;amp; lists) {
    typedef pair&amp;lt;ListNode*, int&amp;gt; pni;

    auto comp = [](const pni &amp;amp; p1, const pni&amp;amp; p2) { 
        return p1.first-&amp;gt;val &amp;gt; p2.first-&amp;gt;val; 
    };

    priority_queue&amp;lt;pni, vector&amp;lt;pni&amp;gt;, decltype(comp)&amp;gt; pq (comp);

    for(int i = 0; i &amp;lt; lists.size(); ++i){
        if(lists[i]){
            pq.push({lists[i], i});
            lists[i] = lists[i]-&amp;gt;next;
        }
    }

    ListNode dh(-1), *curr = &amp;amp;dh;

    while(!pq.empty()){
        const auto p = pq.top(); pq.pop();

        curr-&amp;gt;next = p.first;
        curr = curr-&amp;gt;next;

        ListNode* next = lists[p.second];
        if(next){
            int idx = p.second;
            pq.push({next, idx});
            lists[p.second] = lists[p.second]-&amp;gt;next;
        }
    }
    return dh.next;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  19. &lt;a href="https://en.wikipedia.org/wiki/Rolling_hash"&gt;Rolling hash&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm"&gt;Rabin Karp&lt;/a&gt; is a great example of how to design a simple and efficient algorithm using intelligently a rolling hash function. It can be used to find a string &lt;em&gt;s&lt;/em&gt; in a text &lt;em&gt;t&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The basic ideas that you need to remember to be able to reconstruct this algorithm are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is an improvement over the brute force method, where you compare &lt;em&gt;s&lt;/em&gt; and every candidate substring, &lt;em&gt;c&lt;/em&gt;, which is inefficient.&lt;/li&gt;
&lt;li&gt;If two strings are the same, they will produce the same hash.&lt;/li&gt;
&lt;li&gt;The inverse is not true: two different strings may produce the same hash.&lt;/li&gt;
&lt;li&gt;Using a rolling hash function we can compute the hash of a new string in O(1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we put all this together, we will efficiently compute hashes and only compare &lt;em&gt;c&lt;/em&gt; and &lt;em&gt;s&lt;/em&gt; when they have the same hash, reducing the number of comparisons and thus the average complexity of our algorithm (worst case, we need to compare all substrings and are back to the brute force method).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://leetcode.com/problems/implement-strstr/"&gt;Find string in text&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Return the index of the first occurrence of needle in a haystack, or -1 if the needle is not part of the haystack.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: haystack = "hello", needle = "ll"&lt;/li&gt;
&lt;li&gt;Output: 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: haystack = "aaaaa", needle = "bba"&lt;/li&gt;
&lt;li&gt;Output: -1&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Based on the above paragraphs, try to code the Rabin-Karp algorithm on your own to solve this problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; int strStr(const string&amp;amp; haystack, const string&amp;amp; needle) {
    int nsize = needle.size();

    if(nsize == 0) 
        return 0;

    int hsize = haystack.size();
    if(nsize &amp;gt; hsize)
        return -1;

    int msbPower = 1;       
    int nhash = 0; 
    int hhash = 0;

    const int mod = 10000009; //A big prime number

    for(int i=0; i&amp;lt;nsize; i++) {
        if(i != 0) {
            msbPower *= 26;
            msbPower %= mod;
        }
        nhash = nhash*26+needle[i];
        nhash %= mod;
        hhash = hhash*26+haystack[i];
        hhash %= mod;
    }

    if(nhash == hhash &amp;amp;&amp;amp; haystack.compare(0, nsize, needle) == 0) 
        return 0;

    for(int i=1; i&amp;lt;=hsize-nsize; i++) {
        hhash -= haystack[i-1]*msbPower; 
        hhash %= mod;
        if(hhash &amp;lt; 0)
            hhash += mod;
        hhash = hhash*26+haystack[i+nsize-1];
        hhash %= mod;
        if(nhash == hhash &amp;amp;&amp;amp; haystack.compare(i, nsize, needle) == 0) 
            return i;
    }
    return -1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  20. How to learn new algorithms and data structures
&lt;/h2&gt;

&lt;p&gt;As I have already mentioned here and in other articles, do not try to memorize things. It is counterproductive. You will end up mixing concepts, giving the right solution to the wrong problem, and forgetting what you have memorized. This is why you need to &lt;strong&gt;understand the algorithms&lt;/strong&gt;. If you understand the basic data structures and can turn your ideas into code, you can also code these algorithms.&lt;/p&gt;

&lt;p&gt;The best way to learn them is how I showed you when I described the Rabin-Karp algorithm:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Understand what problem this algorithm or data structure is trying to solve&lt;/strong&gt;: Here, learning where other alternatives fall short is helpful.&lt;br&gt;
2.&lt;strong&gt;Break it down to the key elements or steps that define the algorithm&lt;/strong&gt;. Understand them individually and how they connect.&lt;br&gt;
&lt;strong&gt;From this, code the algorithm&lt;/strong&gt;. &lt;/p&gt;
&lt;h3&gt;
  
  
  Example 1: Binary search
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Binary search is an improvement over a linear search for &lt;strong&gt;sorted arrays&lt;/strong&gt;. It reduces the size of the array in half at every step, achieving a complexity of O(logN) instead of N.&lt;/li&gt;
&lt;li&gt;Two points:
a)Since the array is sorted, &lt;strong&gt;comparing our &lt;em&gt;target&lt;/em&gt; to the middle element of the array&lt;/strong&gt; lets us discard half of the array at every step (the half containing elements that are too large or too small compared to the &lt;em&gt;target&lt;/em&gt;.
b)If the pointers cross, this is &lt;em&gt;l&lt;/em&gt; &amp;gt; &lt;em&gt;r&lt;/em&gt;, there is no solution.
3.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template&amp;lt;typename T&amp;gt;
int binary_search(const vector&amp;lt;T&amp;gt;&amp;amp; v, int k) {
    int l = 0, r = v.size() - 1;
    while(l&amp;lt;=r) {
     const int m = l + (r - l) / 2;
     if(k == v[m]) {
         return m;
     } else if (k &amp;gt; v[m]) {
         l = m + 1;
     } else {
         r = m - 1;
     }
    }
    return -1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Example 2: &lt;a href="https://en.wikipedia.org/wiki/Quadtree"&gt;Quad-tree&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I wanted to show you how this breakdown process can be applied to a much more complex data structure. It is very unlikely that you will need to know about quad-trees for an interview. I just read about them once and found them so interesting that I decided to implement them. &lt;/p&gt;
&lt;h3&gt;
  
  
  What is a quad-tree?
&lt;/h3&gt;

&lt;p&gt;From Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A quadtree is a tree data structure in which &lt;em&gt;each internal node has exactly four children&lt;/em&gt;. Quadtrees are the two-dimensional analog of octrees and are &lt;em&gt;most often used to partition a two-dimensional space by recursively subdividing it into four quadrants or regions&lt;/em&gt;...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  What problem is it trying to solve?
&lt;/h3&gt;

&lt;p&gt;Now that we know the formal definition, I think it is easier to get an intuitive idea of what quadtrees can do from one of its applications.&lt;/p&gt;

&lt;p&gt;Imagine we are trying to model a physical system made of a bunch of particles, each having a certain mass. Every particle attracts every other particle in the system. If we have N particles, at every step of our simulation, the number of interactions we need to process grows as N^2. This will be extremely slow for large values of N. &lt;/p&gt;

&lt;p&gt;Since the attraction between two particles decays with the square of the distance, we can neglect the contribution of particles that are far. How do we know which particles are far &lt;em&gt;without iterating through all the particles&lt;/em&gt; (the problem we are trying to avoid in the first place)? Here is where quadtrees come in handy.&lt;/p&gt;

&lt;p&gt;Using quadtrees, we can efficiently query all the particles in a certain region. The lookup takes O(logN) time, making our overall time for every step O(n log n) since we have to do this for N particles.&lt;/p&gt;

&lt;p&gt;Notice how at this point we do not care so much about the implementation. This is more of a &lt;strong&gt;high-level understanding of the data structure and to get an idea of where it can be useful&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the next section, we will get into more detail.&lt;/p&gt;
&lt;h3&gt;
  
  
  What are the key elements of a quad-tree?
&lt;/h3&gt;

&lt;p&gt;Let's go back to the definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A quadtree is a tree data structure in which &lt;em&gt;each internal node has exactly four children&lt;/em&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;They decompose space into adaptable cells&lt;/li&gt;
&lt;li&gt;Each cell (or bucket) has a maximum capacity. When maximum capacity is reached, the bucket splits&lt;/li&gt;
&lt;li&gt;The tree directory follows the spatial decomposition of the quadtree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, our quadtree class is not very different from any other tree that you may have encountered (including the trie I presented earlier). Each node will contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An integer representing its maximum capacity&lt;/li&gt;
&lt;li&gt;A boolean indicating whether it is a leaf or not (which means, the node has been divided because it reached its maximum capacity)&lt;/li&gt;
&lt;li&gt;Pointers to it 4 children&lt;/li&gt;
&lt;li&gt;An array of containing the points included in that node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knowing what problem a data structure is trying to solve and breaking it down to its basic elements makes it much easier to implement it and especially to &lt;strong&gt;remember what the data structure is about and when it can be used&lt;/strong&gt;. All you have to “memorize” is its definitions and properties - which are easier to remember if you think about what it is trying to solve.&lt;/p&gt;
&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;You can try to implement it in your favorite language &lt;a href="https://leetcode.com/problems/construct-quad-tree/"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution {
private:
    Node *constructHelper(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;grid, int len, int x, int y) {
        int flag = grid[x][y];
        for (int i = x; i &amp;lt; x + len; i++)
            for (int j = y; j &amp;lt; y + len; j++)
                //if not a leaf, go deeper
                if (flag != grid[i][j])
                {
                    Node *tl = constructHelper(grid, len / 2, x, y);
                    Node *tr = constructHelper(grid, len / 2, x, y + len / 2);
                    Node *bl = constructHelper(grid, len / 2, x + len / 2, y);
                    Node *br = constructHelper(grid, len / 2, x + len / 2, y + len / 2);
                    return new Node(true, false, tl, tr, bl, br);
                }
        return new Node(grid[x][y] == 1, true, nullptr, nullptr, nullptr, nullptr);
    }

public:
    Node *construct(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;grid) {
        int n = grid.size();
        return (n == 0) ? nullptr : constructHelper(grid, n, 0, 0);
    }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to learn more about this data structure, I recommend &lt;a href="https://www.youtube.com/watch?v=OJxEcs0w_kE"&gt;these&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=QQx_NmCIuCY"&gt;two&lt;/a&gt; to see a quadtree in action.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nice to know
&lt;/h4&gt;

&lt;p&gt;Here is a list of other topics that are good to know and I have not explicitly mentioned in the article. You don’t need to learn them all in one sitting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure"&gt;Disjoin sets&lt;/a&gt;. Very handy to solve many problems and easy to implement using arrays or tree-like structures.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Shortest_path_problem"&gt;Shortest path algorithms&lt;/a&gt;. &lt;a href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm"&gt;Dijktra’s algorithm&lt;/a&gt;, and at least knowing that there is a “heuristically-optimized version” &lt;a href="https://en.wikipedia.org/wiki/A*_search_algorithm"&gt;A*&lt;/a&gt;. Also &lt;a href="https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm"&gt;Bellman-Ford&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm"&gt;Floyd-Warshall&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Minimum_spanning_tree"&gt;Minimum spanning trees&lt;/a&gt;. What they are and how to compute them. These two are the most common algorithms: &lt;a href="https://en.wikipedia.org/wiki/Kruskal%27s_algorithm"&gt;Kruskal’s&lt;/a&gt; (essentially, sorting edges and computing connected components, which can easily be done using disjoint sets) and &lt;a href="https://en.wikipedia.org/wiki/Prim%27s_algorithm"&gt;Prim’s&lt;/a&gt; (very similar to Dijkstra's shortest path algorithm).&lt;/li&gt;
&lt;li&gt;Balanced trees. There are many types, but knowing &lt;a href="https://en.wikipedia.org/wiki/Red_black_tree"&gt;red-black trees&lt;/a&gt; is enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;I have presented a list of 20 techniques that you will make your next interview a breeze. You will be using some of them at work too, or they might inspire you for side projects. &lt;/p&gt;

&lt;p&gt;The point is not to learn every single data structure or algorithm in a book. As you can see, most of them are either basic techniques or small tweaks on basic data structures you already knew. I want to show you that you can achieve a lot with what you already know.&lt;/p&gt;

&lt;p&gt;PS: I hope you found this useful. If so, like and share this article, visit my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;, and let's connect on &lt;a href="https://twitter.com/CodingLanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>computerscience</category>
      <category>cpp</category>
    </item>
    <item>
      <title>All you need to know about Dynamic Programming
</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Wed, 12 Aug 2020 10:18:10 +0000</pubDate>
      <link>https://dev.to/codinglanguages/all-you-need-to-know-about-dynamic-programming-4bio</link>
      <guid>https://dev.to/codinglanguages/all-you-need-to-know-about-dynamic-programming-4bio</guid>
      <description>&lt;p&gt;This article was originally published in my blog &lt;a href="http://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is dynamic programming and why should you care about it?
&lt;/h1&gt;

&lt;p&gt;In this article, I will introduce the concept of dynamic programming, developed by Richard Bellman in the 1950s, a powerful algorithm design technique to solve problems by breaking them down into smaller problems, storing their solutions, and combining these to get to the solution of the original problem. &lt;/p&gt;

&lt;p&gt;The hardest problems asked in FAANG coding interviews usually fall under this category. It is likely that you will get tasked with solving one during your interviews, hence the importance of knowing this technique. I will explain what dynamic programming is, give you a recipe to tackle dynamic programming problems, and will take you through a few examples so that you can understand better when and how to apply it.&lt;/p&gt;

&lt;p&gt;As I already did in my previous post about &lt;a href="https://dev.to/codinglanguages/how-to-ace-coding-interviews-the-ultimate-guide-5567"&gt;coding interviews&lt;/a&gt;, I will share my thought process when solving problems that can be solved using this methodology, so that you can do the same when you face one of them. I don't want you to memorize anything. You need to understand the technique and practice to acquire the skill of turning ideas into code. Coding is not about learning programming languages. It is about analyzing a problem, considering different solutions, choosing the best one, and then implementing it in some programming language.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dynamic programming
&lt;/h1&gt;

&lt;p&gt;Dynamic programming is a general technique for solving optimization, search and counting problems that can be decomposed into subproblems. To apply dynamic programming, the problem &lt;strong&gt;must&lt;/strong&gt; present the following two attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimal substructure.&lt;/li&gt;
&lt;li&gt;Overlapping subproblems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Optimal substructure
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A problem has optimal substructure if the optimal solution to a problem of size n can be derived from the optimal solution of the same instance of that problem of size smaller than n. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, if the shortest path to go from Paris to Moscow goes through Berlin, it will be made of the shortest path from Paris to Berlin and the shortest path from Berlin to Moscow.&lt;/p&gt;

&lt;p&gt;If a problem can be solved by combining optimal solutions to &lt;strong&gt;non-overlapping&lt;/strong&gt; subproblems, the strategy is called &lt;em&gt;divide and conquer&lt;/em&gt;. This is why merge sort and quick sort are not classified as dynamic programming problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overlapping subproblems
&lt;/h2&gt;

&lt;p&gt;Let's take an example you're probably familiar with, the Fibonacci numbers, where every number is the sum of the previous two Fibonacci numbers. The Fibonacci series can be expressed as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F(0) = F(1) = 1
F(n) = F(n-1) + F(n-2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;They say a picture is worth a thousand words, so here it is (from Elements of programming interviews):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gZ3BRCuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1595961157040/sSp0lOkB_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gZ3BRCuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1595961157040/sSp0lOkB_.png" alt="fib.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve F(n), you need to solve F(n-1) and F(n-2), but F(n-1) needs F(n-2) and F(n-3). F(n-2) is repeated, coming from two different instances of the same problem - computing &lt;strong&gt;a&lt;/strong&gt; Fibonacci number. &lt;/p&gt;

&lt;p&gt;This can be expressed in a recursive function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To solve a problem of size n, you call the same function to solve an instance of the same problem, but of a smaller size.&lt;/li&gt;
&lt;li&gt;You keep calling the function until you hit a &lt;strong&gt;base case&lt;/strong&gt;, in this example, n = 0 or n = 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This leads us to the relationship between recursion and dynamic programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursion and dynamic programming
&lt;/h2&gt;

&lt;p&gt;Conceptually dynamic programming involves recursion. You want to solve your problem based on smaller instances of the same problem, and recursion is a natural way of expressing this in code. The difference with a pure recursive function is that we will trade space for time: we will store the optimal solution to the subproblems to be able to efficiently find the optimal solution to the problem that we originally wanted to solve.&lt;/p&gt;

&lt;p&gt;This is not to say that you must use recursion to solve dynamic programming problems. There is also an iterative way of coding a dynamic programming solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom-up dynamic programming
&lt;/h2&gt;

&lt;p&gt;You need to fill a table with the solution to all the subproblems (starting from the base cases) and use it to build the solution you are looking for. This is done in an iterative fashion, using one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A multidimensional array (1D too) - the most commonly used.&lt;/li&gt;
&lt;li&gt;A hash table.&lt;/li&gt;
&lt;li&gt;A binary search tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as your data structure to store the solutions to the subproblems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top-down dynamic programming
&lt;/h2&gt;

&lt;p&gt;Code the recursive algorithm and add a cache layer to avoid repeating function calls.&lt;/p&gt;

&lt;p&gt;This will all be much clearer when we start with the examples.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to attack a dynamic programming problem
&lt;/h1&gt;

&lt;p&gt;Optimal substructure and overlapping subproblems are the two attributes a problem must have to be solved used dynamic programming. You will need to verify this when your intuition tells you dynamic programming might be a viable solution.&lt;/p&gt;

&lt;p&gt;Let's try to get a feel for what kind of problems can be solved using dynamic programming. Things that start like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find the first n elements ...&lt;/li&gt;
&lt;li&gt;Find all ways...&lt;/li&gt;
&lt;li&gt;In how many ways ...&lt;/li&gt;
&lt;li&gt;Find the n-th ...&lt;/li&gt;
&lt;li&gt;Find the most optimal way...&lt;/li&gt;
&lt;li&gt;Find the minimum/maximum/shortest path ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are potential &lt;em&gt;candidates&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to solve a dynamic programming problem
&lt;/h2&gt;

&lt;p&gt;Unfortunately, there is no universal recipe to solve a dynamic programming problem. You need to go through many problems until you start getting the hang of it. Do not get discouraged. This is hard. Maybe the hardest type of problems you will face in an interview. This is about modeling a problem with relatively simple tools - no need for fancy data structures or algorithms.&lt;/p&gt;

&lt;p&gt;I have solved tons of them and still, sometimes I find it difficult to get to the solution. The more you practice, the easier it will be. This is the closest to a recipe to solve dynamic programming problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prove overlapping subproblems and suboptimal structure properties.&lt;/li&gt;
&lt;li&gt;Define subproblems.&lt;/li&gt;
&lt;li&gt;Define recursion.&lt;/li&gt;
&lt;li&gt;Code your top-down or bottom-up dynamic programming solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Complexity analysis varies from problem to problem, but in general, the time complexity can be expressed as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Time ~ Number of subproblems * time per subproblem&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is straightforward to compute the space complexity for a bottom-up solution since it is equal to the space required to store solutions to the subproblems (multidimensional array).&lt;/p&gt;

&lt;h1&gt;
  
  
  Examples
&lt;/h1&gt;

&lt;p&gt;I've categorized some problems according to the number of independent dimensions involved. This is not necessary, but something that I have found it useful to have a mental model to follow when designing a solution. You will see &lt;em&gt;patterns&lt;/em&gt;, as you code more and more. This is one of them (which I have not found explicitly described anywhere else). Use it if you find it helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  1D problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fibonacci
&lt;/h3&gt;

&lt;p&gt;Since by now you are very familiar with this problem, I am just going to present the recursive solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int fib(int n) {
  if (n == 0 || n == 1)
    return 1;
  else
    return fib(n - 1) + fib(n - 2);
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Going from recursive to top-down is usually mechanical: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the value you need is already in the cache. If so, return it.&lt;/li&gt;
&lt;li&gt;Otherwise, cache your solution before returning.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int fib(int n) {
  vector&amp;lt;int&amp;gt; cache(n + 1, -1);
  return fib_helper(n, cache);
}

int fib_helper(int n, vector&amp;lt;int&amp;gt; &amp;amp;cache) {
   if(-1 != cache[n])
     return cache[n];

   if (n == 0 || n == 1)
     cache[n] = 1;
  else
    cache[n] = fib_helper(n - 1, cache) + fib_helper(n - 2, cache);
  return cache[n];
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here, the bottom-up solution, where we build a table (from the base cases) to form the solution to the problem we're looking for. This table is a 1D array: we only need to store the solution to a smaller version of the same problem to be able to derive the solution to the original problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int fib(int n) { 
    vector&amp;lt;int&amp;gt; f(n + 1, 0);  

    f[1] = 1; 

    for(int i = 2; i &amp;lt;= n; i++) 
       f[i] = f[i - 1] + f[i - 2]; 

    return f[n]; 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Extra space optimization
&lt;/h4&gt;

&lt;p&gt;This approach could be further optimized in memory, not time (there are faster techniques to compute Fibonacci numbers, but that is a topic for another article), by using just 3 variables instead of an array since we only need to keep track of 2 values, f(n-1) and f(n-2), to produce the output we want, f(n).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int fib(int n) {  
    if (n == 0 || n == 1) 
      return 1;

    //Variables that represent f(n - 1), f(n - 2) and f(n)
    int n1= 1, n2 = 1, f = 0; 

    for (int i = 2; i &amp;lt;= n; i++) { 
        f= n1 + n2; 
        n2 = n1; 
        n1 = f; 
    }
    return f;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is more advance, but a common pattern. If you only need to keep track of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A few variables, you might be able to get rid of the 1D array and turn it into a few variables.&lt;/li&gt;
&lt;li&gt;A few rows in a 2D matrix, you might be able to reduce it to a couple of 1D arrays.&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reducing dimensions we improve our space complexity. For now, you can forget about this, but after you get some practice, try to come up with these optimizations yourself to increase your ability to analyze problems and turn your ideas into code. In an interview, I would just go for the simpler version, just discussing potential optimizations and only implementing them if there is enough time after coding your "standard" dynamic programming solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Climbing stairs
&lt;/h3&gt;

&lt;p&gt;You are climbing a staircase. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps.  In how many distinct ways can you climb to the top?&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 2&lt;/li&gt;
&lt;li&gt;Output: 2&lt;/li&gt;
&lt;li&gt;Explanation: There are two ways to climb to the top: 1 step + 1 step and 2 steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 3&lt;/li&gt;
&lt;li&gt;Output: 3&lt;/li&gt;
&lt;li&gt;Explanation: There are three ways to climb to the top: 1 step + 1 step + 1 step, 1 step + 2 steps and 2 steps + 1 step&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Try to solve this problem on your own. You might be able to come up with a recursive solution. Go through my explanation and the previous examples to see if you can code a top-down solution.&lt;/p&gt;

&lt;p&gt;A little hint: The fact that the question starts with &lt;strong&gt;"In how many ways"&lt;/strong&gt;, should already make you think of a potential candidate for dynamic programming. &lt;/p&gt;

&lt;p&gt;In this case, you want to reach step N. You can reach step number N from step N - 1 or N - 2 because you can jump 1 or 2 steps at a time. If you can solve these two subproblems, you can find the solution to the general problem. Let's call f(N) the number of ways you can get to step N.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To get f(N), you need f(N - 1) and f(N - 2).&lt;/li&gt;
&lt;li&gt;To get to f(N - 1), you need f(N- 2) and f(N - 3).&lt;/li&gt;
&lt;li&gt;For f(N - 2), you need f(N - 3) and  f(N - 4).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't need to continue. You can already see that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This problem has overlapping subproblems: you'll need to compute multiple times f(N - 2), f(N - 3), f(N - 4), ...&lt;/li&gt;
&lt;li&gt;This problem presents optimal substructure: with the optimal solution to f(N - 1) and f(N - 2), you can get the optimal solution to f(N).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which means dynamic programming can be used to solve it. &lt;/p&gt;

&lt;p&gt;I will not write the code for this problem because ... I have already done it in the previous example!&lt;/p&gt;

&lt;p&gt;You can write and test your solution &lt;a href="https://leetcode.com/problems/climbing-stairs/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Longest increasing subarray
&lt;/h3&gt;

&lt;p&gt;Given an unsorted array of integers, find the length of the longest increasing subsequence.&lt;br&gt;
[10,9,2,5,3,7,101,18]&lt;/p&gt;

&lt;p&gt;The output would be 4, for the sequence [2,3,7,101]&lt;/p&gt;
&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We need to find the length of the &lt;strong&gt;longest&lt;/strong&gt; increasing subsequence for an array of size n. This sounds like an optimization problem, which could be a candidate for dynamic programming, so let's try. Imagine that you already have the solution for a problem of size N  -  let's call it s(n) - and you add an extra element to the array, called Y. Can you reuse part of the solution to X to solve this new problem? This mental experiment usually gives some good insight into the problem.&lt;/p&gt;

&lt;p&gt;In this case, you need to know if the new element can extend one of the existing sequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Iterate through every element in the array, let's call it X.&lt;/li&gt;
&lt;li&gt;If the new element Y is greater than X, the sequence can be extended by one element.&lt;/li&gt;
&lt;li&gt;If we have stored the solution to all the subproblems, getting the new length is trivial - just a lookup in an array. We can generate the solution to the new problem from the optimal solution to the subproblems.&lt;/li&gt;
&lt;li&gt;Return the length of the new longest increasing subsequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We seem to have an algorithm. Let's continue our analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimal substructure: we've verified that the optimal solution to a problem of size n can be computed from the optimal solution to the subproblems.&lt;/li&gt;
&lt;li&gt;Overlapping subproblems: To compute s(n), I'll need s(0), s(1), ..., s(n-1). In turn, for s(n-1), I'll need s(0), s(1), ..., s(n-2). The same problems needs to be computed multiple times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the code for the bottom-up solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int lengthOfLIS(const vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        if(nums.empty())
            return 0;

        vector&amp;lt;int&amp;gt; dp(nums.size(), 1);
        int maxSol = 1;

        for(int i = 0; i &amp;lt; nums.size(); ++i){
            for(int j = 0; j &amp;lt; i; ++j){
                if(nums[i] &amp;gt; nums[j]){
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            maxSol = max(maxSol, dp[i]);
        }
        return maxSol;   
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can write and test your solution &lt;a href="https://leetcode.com/problems/longest-increasing-subsequence/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many &lt;a href="https://en.wikipedia.org/wiki/Binary_search_tree"&gt;BST&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Given n, how many structurally unique BSTs (binary search trees) that store values 1 ... n?&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: 5&lt;/li&gt;
&lt;li&gt;Output: 42&lt;/li&gt;
&lt;li&gt;Explanation: Given n = 5, there are a total of 42 unique BST's&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Let's go through that example. Let's imagine we have numbers the numbers 1,2,3,4,5. How can I define a BST?&lt;/p&gt;

&lt;p&gt;The only thing I really need to do is to pick one of the numbers as the root. Let's say that element is number 3. I will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 as root&lt;/li&gt;
&lt;li&gt;Numbers 1 and 2 to the left of 3.&lt;/li&gt;
&lt;li&gt;Numbers 4 and 5 to the right of 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can solve the same subproblem for (1,2) - let's call this solution L - and (4,5) - let's call this solution R -  and count how many BST can be formed with 3 as its root, which is the product L * R. If we do this for every possible root and add all the results up, we have our solution, C(n). As you can see, being methodical and working from a few good examples helps design your algorithms. &lt;/p&gt;

&lt;p&gt;In fact, this is all that needs to be done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick an element as the root of the BST.&lt;/li&gt;
&lt;li&gt;Solve the same problem for numbers (1 to root - 1) and (root + 1 to n).&lt;/li&gt;
&lt;li&gt;Multiply both the results for each &lt;em&gt;subproblem&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Add this to our running total.&lt;/li&gt;
&lt;li&gt;Move to the next root.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, we don't really care what numbers lie in each side of the array. We just need the size of the subtrees, i.e. the number of elements to the left and to the right of the root. Every instance of this problem will produce the same result. In our previous example, L is the solution to C(2) and so is R. We only need to compute C(2) once, cache it, and reuse it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    int numTrees(int n) {
        vector&amp;lt;int&amp;gt; dp(n + 1, 0);

        dp[0] = 1;
        dp[1] = 1;

        for(int i = 2; i &amp;lt;= n; ++i){
            for(int j = 0; j &amp;lt; i; ++j){
                dp[i] += dp[j] * dp[i - 1 - j];
            }
        }
        return dp.back();
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can code and test your solution &lt;a href="https://leetcode.com/problems/unique-binary-search-trees/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2D problems
&lt;/h2&gt;

&lt;p&gt;These problems are usually a little harder to model because they involve two dimensions. A common example is a problem where you have to iterate through two strings or to move through a map.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The top-down solution is not much different: find the recursion and use a cache (in this case, your key will be based on 2 "indices")&lt;/li&gt;
&lt;li&gt;For the bottom-up, a 2D array will suffice to store the results. This might be reduced one or a couple of 1D arrays as I mentioned before, but don't stress about this. I'm just mentioning it in case you see it when solving a problem. As I said in my other article, learning is iterative. First, focus on understanding the basics and add more and more details little by little.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Minimum path sum
&lt;/h3&gt;

&lt;p&gt;Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.&lt;/p&gt;

&lt;p&gt;Note: You can only &lt;em&gt;move either down or right&lt;/em&gt; at any point in time.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input:
[  [1,3,1],
[1,5,1],
[4,2,1] ]&lt;/li&gt;
&lt;li&gt;Output: 7&lt;/li&gt;
&lt;li&gt;Explanation: Because the path 1→3→1→1→1 minimizes the sum.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Minimizes&lt;/em&gt; should make you think of dynamic programming. Let's analyze this further. We can get from any cell C with indices (i,j) (that is not on the top or left border) from cells A = (i-1, j) and B = (i,j-1). From this, we can see that some problems are going to be computed multiple times. Also, we if know the optimal solution to A and B, we can compute the optimal solution to the current cell as min(sol(A), sol(B)) + 1 - since we can only get to the current cell form A or B and we need one extra step to move from these cells to the current cell. In other words, this problem presents optimal substructure and overlapping problems. We can use dynamic programming.&lt;/p&gt;

&lt;p&gt;Here's the bottom-up solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    int minPathSum(const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; grid) {
        const int nrow = grid.size();

        if(nrow == 0)
            return 0;

        const int ncol = grid[0].size();

        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; minSum(nrow, vector&amp;lt;int&amp;gt;(ncol, 0));
        minSum[0][0] = grid[0][0];

        for(int col = 1; col &amp;lt; ncol; ++col)
            minSum[0][col] = minSum[0][col - 1] + grid[0][col];

        for(int row = 1; row &amp;lt; nrow; ++row)
            minSum[row][0] = minSum[row - 1][0] + grid[row][0];

        for(int col = 1; col &amp;lt; ncol; ++col){
            for(int row = 1; row &amp;lt; nrow; ++row){
                minSum[row][col] = min(minSum[row - 1][col], minSum[row][col - 1]) + grid[row][col];
            }
        }
        return minSum[nrow - 1][ncol - 1];
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The boundary conditions are defined over the border of the matrix. You can only get to the elements in the border in one way: moving one square to the right or down from the previous element.&lt;/p&gt;

&lt;p&gt;You can code and test your solution &lt;a href="https://leetcode.com/problems/minimum-path-sum/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knapsack problem
&lt;/h3&gt;

&lt;p&gt;Given two integer arrays val[0..n-1] and wt[0..n-1] which represent values and weights associated with n items respectively. Also given an integer W which represents knapsack capacity, find out the maximum value subset of val[] such that the sum of the weights of this subset is smaller than or equal to W. You cannot break an item, either pick the complete item or don’t pick it (0-1 property).&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Try to come up with a recursive solution. From there, add a cache layer and you'll have a top-down dynamic programming solution!&lt;/p&gt;

&lt;p&gt;The main idea is that, for every item, we have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can add the item to the bag (If it fits), increase our total value, and decrease the capacity of the bag.&lt;/li&gt;
&lt;li&gt;We can skip that item, keep the same value, and the same capacity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After we've gone through every single combination, we just need to pick the max value. This is extremely slow, but it's the first step towards a solution.&lt;/p&gt;

&lt;p&gt;Having to decide between two options (add an element to a set or skip it) is a very common pattern that you will see in many problems, so it's worth knowing it and understanding when and how to apply it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Recursive. Try to turn this into a piece of top-down DP code.
int knapSack(int W, int wt[], int val[], int n) { 
     if (n == 0 || W == 0) 
        return 0; 

    if (wt[n - 1] &amp;gt; W) 
        return knapSack(W, wt, val, n - 1); 
    else
        return max(val[n - 1] + knapSack(W - wt[n - 1],  wt, val, n - 1), knapSack(W, wt, val, n - 1)); 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A bottom-up solution is presented here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C style, in case you are not familiar with C++ vectors
int knapSack(int W, int wt[], int val[], int n) 
{ 
    int i, w; 
    int K[n + 1][W + 1]; 

    for (i = 0; i &amp;lt;= n; i++) { 
        for (w = 0; w &amp;lt;= W; w++) { 
            if (i == 0 || w == 0) 
                K[i][w] = 0; 
            else if (wt[i - 1] &amp;lt;= w) 
                K[i][w] = max( val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]); 
            else
                K[i][w] = K[i - 1][w]; 
        } 
    } 
    return K[n][W]; 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Longest common subsequence (LCS)
&lt;/h3&gt;

&lt;p&gt;Given two strings text1 and text2, return the length of their longest common subsequence.&lt;/p&gt;

&lt;p&gt;A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, "ace" is a subsequence of "abcde" while "aec" is not). A common subsequence of two strings is a subsequence that is common to both strings.&lt;/p&gt;

&lt;p&gt;If there is no common subsequence, return 0.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: text1 = "abcde", text2 = "ace" &lt;/li&gt;
&lt;li&gt;Output: 3
&lt;/li&gt;
&lt;li&gt;Explanation: The longest common subsequence is "ace" and its length is 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Again, compute the &lt;strong&gt;longest&lt;/strong&gt; X makes me think that dynamic programming could help here.&lt;/p&gt;

&lt;p&gt;Since you already have some experience with dynamic programming, I'll go straight to the 2 properties, from the example. Let's call the strings A and B, and our solution to this problem f(A, B). The idea is to see whether the 2 last characters are equal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If so, the LCS has at least length 1. We need to call f(A[0:n-1], B[0:n-1]) to find the LCS till that index, and add 1 because A[n] and B[n] are the same.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If not, we remove that last character from both strings -one at a time - and find which path produces the LCS. In other words, we take the maximum of f(A[0: n -1], B) and f(A, B[0:n-1])&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overlapping subproblems: Let's see what calls can we expect: ("abcde", "ace") produces x1 = ("abcd", "ace") and y1 = ("abcde", "ac");  x1 will produce x12 = ("abc", "ace") and y12= ("abcd", "ac"); y1 will produce ("abcd", "ac") and ("abcde", "a"). As you can see, the problems same problems need to be computed multiple times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimal substructure: Very similar to the longest increasing subsequence. If we add one extra character to one of the strings, A', we can quickly compute the solution from all the cached results that we obtained from solving for A and B.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using examples to prove things is not the way you start a mathematical demonstration, but for a coding interview is more than enough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int longestCommonSubsequence(const string &amp;amp;text1, const string &amp;amp;text2) {
        const int n = text1.length();
        const int m = text2.length();

        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; dp(n + 1, vector&amp;lt;int&amp;gt;(m + 1,0));

        for(int i = 1; i &amp;lt;= n; i++){
            for(int j = 1; j &amp;lt;= m; j++){
                if(text1[i-1] == text2[j-1]) 
                    dp[i][j] = dp[i-1][j-1]+1;
                else 
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
        return dp[n][m];
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can code and test your solution &lt;a href="https://leetcode.com/problems/longest-common-subsequence/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  More resources
&lt;/h1&gt;

&lt;p&gt;For more exercises, check the resources I listed in my previous article. For more dynamic programming specific content, the following videos are a great place to start. They get in more detail and cover other problems I have purposely not addressed here to give you more variety. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=OQ5jsbhAv_M&amp;amp;list=PLcDimPvbmfT8qAxD6JH_kmXiQwTNcoK78"&gt;MIT lecture on dynamic programming #1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ENyox7kNKeY&amp;amp;list=PLcDimPvbmfT8qAxD6JH_kmXiQwTNcoK78&amp;amp;index=2"&gt;MIT lecture on dynamic programming #2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ENyox7kNKeY&amp;amp;list=PLcDimPvbmfT8qAxD6JH_kmXiQwTNcoK78&amp;amp;index=3"&gt;MIT lecture on dynamic programming #3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tp4_UXaVyx8&amp;amp;list=PLcDimPvbmfT8qAxD6JH_kmXiQwTNcoK78&amp;amp;index=4"&gt;MIT lecture on dynamic programming #4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, check out the &lt;a href="https://en.wikipedia.org/wiki/Dynamic_programming"&gt;Wikipedia article for DP&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You need to become familiar with these problems because many others are just variations on these. But do not memorize them. Understand when and how to apply dynamic programming, and practice until you can easily turn your ideas into working code. As you have seen, it is about being methodical. You don't need advanced knowledge of algorithms or data structures to solve the problems. Arrays are enough.&lt;/p&gt;

&lt;p&gt;I have not completed a time/space analysis. That is an exercise for you. Feel free to reach out with questions or comments.&lt;/p&gt;

&lt;p&gt;PS: I hope you found this useful. If so, like and share this article, visit my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;, and let's connect on &lt;a href="https://twitter.com/CodingLanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>100daysofcode</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to ace coding interviews. The ultimate guide.
</title>
      <dc:creator>Your DevOps Guy</dc:creator>
      <pubDate>Mon, 10 Aug 2020 18:57:38 +0000</pubDate>
      <link>https://dev.to/codinglanguages/how-to-ace-coding-interviews-the-ultimate-guide-5567</link>
      <guid>https://dev.to/codinglanguages/how-to-ace-coding-interviews-the-ultimate-guide-5567</guid>
      <description>&lt;p&gt;This article was originally published in my blog &lt;a href="http://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why should you read this guide?
&lt;/h1&gt;

&lt;p&gt;I must have been in almost a hundred coding interviews. Sometimes as an interviewee and sometimes as an interviewer. I have struggled in front of the whiteboard and I have seen many candidates struggle.&lt;/p&gt;

&lt;p&gt;Getting a job at a FAANG company (Facebook, Amazon, Apple, Netflix, Google) can provide you, among other things, the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Great compensation&lt;/li&gt;
&lt;li&gt;Fantastic working environment&lt;/li&gt;
&lt;li&gt;Challenging work&lt;/li&gt;
&lt;li&gt;Smart colleagues&lt;/li&gt;
&lt;li&gt;An impressive CV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did it and I can tell you it is absolutely worth it. &lt;/p&gt;

&lt;p&gt;This will not be another 'How to crack the Google interview' guide, rehashing the same generic tips: study hard, practice, relax, and sleep well the day before the interview. This is based on years of experience, both as a candidate and as an interviewer. &lt;/p&gt;

&lt;p&gt;You are not alone if you feel that coding interviews are far from perfect - I am there with you - but it is the game you have to play if you want the job. I have been rejected several times and I also have cracked the Amazon interview in just two months of study, while I had a full-time job. I have learned a lot in this process.&lt;/p&gt;

&lt;p&gt;I do not have a degree in computer science. I had to start from scratch. This is the guide I wish I have had when I started my journey as a developer.&lt;/p&gt;

&lt;p&gt;Not being at a FAANG (Facebook, Amazon, Apple, Netflix, Google) company does not mean you are not a great developer. It only means you haven't cracked the interviews yet. Keep reading if you want to get a step by step guide on how to prepare to get that job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;p&gt;This is what I will cover in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The right mindset before, during and after the interview&lt;/li&gt;
&lt;li&gt;How to practice solving coding challenges&lt;/li&gt;
&lt;li&gt;Technical knowledge required&lt;/li&gt;
&lt;li&gt;Books and websites I used&lt;/li&gt;
&lt;li&gt;Mistakes to avoid before and during the interview&lt;/li&gt;
&lt;li&gt;Examples&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How to prepare
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Mindset
&lt;/h2&gt;

&lt;p&gt;Developers at FAANG companies are not gods. They are regular human beings who went through the same process as you, with their own problems and insecurities. They also suffered from impostor syndrome - probably still do it. Do not put them on a pedestal. Keep this in mind at all times, especially when you get the job.&lt;/p&gt;

&lt;p&gt;I have met interviewers who enjoyed torturing candidates. Some interviewers who would not hire some of their teammates. Luckily, they are a minority, but you might encounter one of them during your set of interviews. The only smart thing to do is to focus on what you can control: your preparation. Focus on the process. If you prepare well and are persistent, it will be a matter of time before you get the job you want. Once there, it will be easy to move to a different company if you feel like it.&lt;br&gt;
You’ll have 4, 5, or 6 rounds of problems to help you, in case you fail in one - or find one of the psycho interviewers I talked about earlier. You can underperform in one of the rounds and still get the job.&lt;/p&gt;

&lt;p&gt;Self-reflection is a great teacher. After every problem you solve and any interview to attend to, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What went well?&lt;/li&gt;
&lt;li&gt;Where do I need to improve?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will range from computer science and programming language related topics to how well you communicate with your interviewer. &lt;/p&gt;

&lt;p&gt;Also, I do recommend applying to multiples companies at the same time, in reverse order of preference. This translates to having more options, which will put you in a better position to negotiate, reduce the pressure you put on yourself and give you more opportunities to practice.&lt;/p&gt;

&lt;p&gt;People eventually leave these companies, be it after 1, 2, 3, or 5 years. It is not paradise, just another job, but this is something that I cannot teach you. You have to see it yourself.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to practice
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Emulate the interview set-up
&lt;/h3&gt;

&lt;p&gt;Try to make your practice sessions as similar to the actual interview as possible. This includes:&lt;/p&gt;
&lt;h4&gt;
  
  
  Time yourself
&lt;/h4&gt;

&lt;p&gt;Depending on the company, you will have around up to one hour to solve a problem. At Amazon, for instance, that hour includes a Leadership Principle related questions, which brings the time for the technical question down to around 40 to 45 minutes. &lt;/p&gt;

&lt;p&gt;Once you start getting the grip of solving the challenges, train yourself to go much faster - 30 minutes tops. This way, the day of the interview, even if you get nervous you will be really well trained. Time flies in an interview.&lt;/p&gt;
&lt;h4&gt;
  
  
  No distractions
&lt;/h4&gt;

&lt;p&gt;Mute your phone. No music. No internet. You want your practice sessions to be as realistic as possible.&lt;/p&gt;
&lt;h4&gt;
  
  
  If you get stuck, keep trying. Do not give up.
&lt;/h4&gt;

&lt;p&gt;During an interview, you cannot just look at the solution. Some platforms and books provide hints. Having a look at these after a few minutes of being blocked is fine as you advance in your preparation since interviewers will likely give you some hints if you get stuck.&lt;/p&gt;
&lt;h4&gt;
  
  
  Think out loud
&lt;/h4&gt;

&lt;p&gt;Interviewers need to know what you are thinking. Your problem-solving skills are being assessed, but your communication skills are under evaluation too. Furthermore, interviewers can steer you in the right direction and save you precious minutes if they see your approach will lead nowhere.&lt;/p&gt;

&lt;p&gt;If you can, find a friend (virtually buddies work too), practice, and give each other constructive feedback.&lt;/p&gt;
&lt;h3&gt;
  
  
  Expand your toolbox
&lt;/h3&gt;

&lt;p&gt;Write down anything new that you didn’t know. Functions you had never seen, cool tricks, new concepts, etc. Go through this list often until they become part of your arsenal and come naturally when you're solving problems on your own.&lt;/p&gt;

&lt;p&gt;For instance, here is a trick to go through all the neighbours (horizontally and vertically) of a cell in a matrix with coordinates (row, col):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; dirs = {{1,0}, {-1,0}, {0, 1}, {0, -1}};
for (const auto&amp;amp; d:dirs) {
  const nextRow = row + d[0];
  const nextCol = col + d[1];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even if C++ is not your main language, just understand the idea and try to translate it into your favourite language. If you want to use C++ in your interviews, make sure you understand every line in that short snippet of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep a log of common mistakes you make
&lt;/h3&gt;

&lt;p&gt;This is one of the things that made a huge difference in my performance. You need to know where you usually underperform so that you can fix it. It can be anything: Big (O), dynamic programming problems, recursive functions, tree-related problems, etc.&lt;/p&gt;

&lt;p&gt;Go through this list often. Review them and practice to make sure you do not make them during your interview.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iterations
&lt;/h3&gt;

&lt;p&gt;As I see it, there are two stages during your preparation. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need to understand all the theoretical concepts and know:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;When, how, and why to apply them.&lt;/li&gt;
&lt;li&gt;When, and why not to apply them&lt;/li&gt;
&lt;li&gt;How to connect them to solve a problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;You need to be able to implement them and &lt;em&gt;turn your ideas into code&lt;/em&gt;. This is what you get paid for.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Stage 1
&lt;/h4&gt;

&lt;p&gt;Focus on quantity. You need to go through many problems until you start developing an intuition that gives you ideas to solve new problems you have never seen. For every new problem, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What algorithm and/or data structure is good for this type of problem?&lt;/li&gt;
&lt;li&gt;Why? &lt;/li&gt;
&lt;li&gt;Why this other approach is worse or wrong?&lt;/li&gt;
&lt;li&gt;What are the time and space complexity of this approach?&lt;/li&gt;
&lt;li&gt;Can I trade time for space?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not about memorizing solutions. I repeat. &lt;strong&gt;Do not memorize the solutions&lt;/strong&gt;. It is useless and worse than a waste of time. Relying on it is buying a ticket to give the perfect solution to the wrong problem. The idea here is to learn to apply all the data structures and algorithms that you have studied. Putting the theory to practice.&lt;/p&gt;

&lt;p&gt;At this stage, I do not write any code. I just do everything I would do before I start writing code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask clarifying questions&lt;/li&gt;
&lt;li&gt;Make sure I understand what the input and expected output are&lt;/li&gt;
&lt;li&gt;Come up with a step by step plan to solve the problem combining (there are examples at the end of this guide)&lt;/li&gt;
&lt;li&gt;Big(O) analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then compare my approach to the solution in the book. If it is different (or worse), understand why and try to see why I couldn't come up with it: maybe I did not know the data structure, I never thought of applying it that way, etc. The idea is to change the way you think to a more elevated one where you can see the different pieces individually and how to combine them to get to a solution.&lt;/p&gt;

&lt;p&gt;During your interviews, if you cannot pass this stage, it does not matter how good you are at Python. You are out.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stage 2
&lt;/h4&gt;

&lt;p&gt;Now, you can focus on writing the code for the problems you've "already solved". Some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not use your IDE. During the interviews, you will not have it. It will be either a whiteboard or an online shared document. Make sure you understand the format of the interview so that you can focus&lt;/li&gt;
&lt;li&gt;If you need to write code on a whiteboard, I'd recommend solving some problems in paper &lt;em&gt;as you get close to the interview&lt;/em&gt;. Writing on a whiteboard is different from typing on a keyboard. It is a skill you will want to practice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a problem is too hard, save it for later. Focus on making progress. This will create positive momentum that will help you tackle harder problems later.&lt;/p&gt;

&lt;p&gt;You can't afford to spend 5 minutes to write a while loop. You need to be in good coding shape. Be very comfortable in your preferred programming language (you can usually choose it). The better you know the language and the more fluent you are, the more time you will have during the interview to focus on the actual problem that you need to solve and to communicate your thoughts to the interviewer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tech knowledge
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you should know
&lt;/h3&gt;

&lt;p&gt;I'll enumerate the main topics you should be familiar with. You must know them cold if you target at FAANG companies.&lt;/p&gt;

&lt;h4&gt;
  
  
  Data structures
&lt;/h4&gt;

&lt;p&gt;Theoretically and how to use them in code&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrays &lt;/li&gt;
&lt;li&gt;Strings &lt;/li&gt;
&lt;li&gt;Lists &lt;/li&gt;
&lt;li&gt;Stacks and queues &lt;/li&gt;
&lt;li&gt;Trees (and tries)&lt;/li&gt;
&lt;li&gt;Binary search trees (balanced)&lt;/li&gt;
&lt;li&gt;Hash tables &lt;/li&gt;
&lt;li&gt;Sets (disjoint sets too if you can)&lt;/li&gt;
&lt;li&gt;Graphs&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Algorithms
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Binary search&lt;/li&gt;
&lt;li&gt;Sorting &lt;/li&gt;
&lt;li&gt;Recursion &lt;/li&gt;
&lt;li&gt;Divide and conquer &lt;/li&gt;
&lt;li&gt;Dynamic programming &lt;/li&gt;
&lt;li&gt;Greedy&lt;/li&gt;
&lt;li&gt;Algorithms on strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On graphs (very important):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DFS&lt;/li&gt;
&lt;li&gt;BFS&lt;/li&gt;
&lt;li&gt;Minimum spanning trees: Kruskal and Prim&lt;/li&gt;
&lt;li&gt;Shortest path: Dijkstra and Floyd-Warshall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some discrete math can help too.&lt;/p&gt;

&lt;h4&gt;
  
  
  Programming languages
&lt;/h4&gt;

&lt;p&gt;I've always used C++, but the following good for interviews too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since most interviewers know them. Most candidates tend to go for Python. Whichever you choose, make sure you know it well.&lt;/p&gt;

&lt;h3&gt;
  
  
  More resources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  MIT courses on algorithms
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp"&gt;This course&lt;/a&gt; is a great introduction to most of the concepts you will need in an interview. &lt;/p&gt;

&lt;p&gt;I would start here and only go to the next book for more in-depth explanations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introduction to algorithms
&lt;/h4&gt;

&lt;p&gt;You do not need to go through the whole book, but it's a good complement to the previous course. It has everything you may need - and much more. Focus on the topics I have listed before. Everything else is &lt;em&gt;nice to know&lt;/em&gt; but the chances of it coming up in an interview are slim.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cracking the coding interview.
&lt;/h4&gt;

&lt;p&gt;I did not start here though. I only completed the problems in the last 2 sections (medium and hard), after I finished the next book.&lt;/p&gt;

&lt;h4&gt;
  
  
  Elements of programming interviews
&lt;/h4&gt;

&lt;p&gt;This is an excellent book. I keep coming back to it before every interview. The questions are hard, so you will be very well prepared. There are C++, Python, and Java versions.&lt;/p&gt;

&lt;p&gt;For more problems, I only used &lt;a href="https://www.leetcode.com"&gt;https://www.leetcode.com&lt;/a&gt;. You'll have more than enough with the free problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistakes to avoid
&lt;/h2&gt;

&lt;p&gt;Let me help you avoid the most common mistakes I have seen so that you can nail your coding interview.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Not preparing
&lt;/h3&gt;

&lt;p&gt;Yes. People go unprepared. I’ve seen many people blank during an interview. I’ve had to cut interviews after 20 minutes. It happens more than you may think.&lt;/p&gt;

&lt;p&gt;Just as a reminder, you need to be good at the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Algorithms&lt;/li&gt;
&lt;li&gt;Data Structures&lt;/li&gt;
&lt;li&gt;Language(s) of your choice&lt;/li&gt;
&lt;li&gt;CS Fundamentals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve previously covered resources for algorithms, data structures, and programming languages (through solving problems, a better way of learning than reading or watching tutorials). You should be able to assess what areas of computer sciences you need to brush up.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Not communicating what you think
&lt;/h3&gt;

&lt;p&gt;We interviewers cannot read your mind. Make sure you think out loud. We can stir you in the right direction before you waste too much time on the wrong approach. We assess your problem-solving skills, but to do that we need to know what you are thinking. Make your interviewer’s life easier and you’ll have a higher chance of landing that job.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Not asking clarifying questions
&lt;/h3&gt;

&lt;p&gt;The questions will be vague, on purpose. Make sure you state all your assumptions &lt;strong&gt;before&lt;/strong&gt; you start solving the problem. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the input sorted?&lt;/li&gt;
&lt;li&gt;Are there repeated elements?&lt;/li&gt;
&lt;li&gt;If no solution, what should I return?&lt;/li&gt;
&lt;li&gt;Do I need to check for invalid inputs?&lt;/li&gt;
&lt;li&gt;How many users do we expect?&lt;/li&gt;
&lt;li&gt;Trade-offs: increase space to be faster?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Solving the wrong problem
&lt;/h3&gt;

&lt;p&gt;Gather all requirements before starting. One small change can make the problem completely different. Repeat the problem using your own words, to buy some time to think about the solution, and to ensure you’re solving the right problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Wasting time
&lt;/h3&gt;

&lt;p&gt;If you don’t remember the API, just say: “Let’s assume the function is like this” and move on. You can assume you have the function you need and then come back to it and write it down in detail. An “imperfect” solution is better than nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Not testing your code
&lt;/h3&gt;

&lt;p&gt;This is a huge red flag, so make sure you don’t fail here. Come up with a few test cases (there is no need to write the actual code):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Happy path”&lt;/li&gt;
&lt;li&gt;Edge cases&lt;/li&gt;
&lt;li&gt;Empty/null input&lt;/li&gt;
&lt;li&gt;Repeated elements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Not debugging it
&lt;/h3&gt;

&lt;p&gt;Take one or several of your previous test cases and run them through your code, line by line. Make sure you get the values you expect. Even if you miss something, the fact that you are doing this already gives a very good impression.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Poor time and space analysis
&lt;/h3&gt;

&lt;p&gt;Learn how to analyze the time and space complexity of your solutions. It’s just a chapter in any of the books I have listed before.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Going for the optimal solution
&lt;/h3&gt;

&lt;p&gt;First, come up with the brute force solution. No matter how slow or obvious it may sound. Having that is already a positive point. You don’t need to write code at this stage, but explain your solution in detail. If you cannot figure out a more optimized way of solving the problem, then you can start coding this solution.&lt;/p&gt;

&lt;p&gt;From there, try to find bottlenecks and come up with an efficient solution (usually using a different data structure or after sorting the input). It’s better than having nothing at the end of the interview because you tried to find the O(1) solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Not being fluent enough in your language of choice
&lt;/h3&gt;

&lt;p&gt;Usually, you can pick up the programming language you want for the interview. If you say you can code in Python, JavaScript or Java, make sure you don’t need 3 minutes to write a for loop (I’ve seen this many times). It is is not the end of the world if you forget API details or a semicolon.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Edge cases
&lt;/h3&gt;

&lt;p&gt;Do not forget to test for edge cases. I cannot stress this enough. Most problems you will be given will be vague and have edge cases just to see if you think of them when you face a new problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Low-quality code
&lt;/h3&gt;

&lt;p&gt;Write clean code. Not just for the interviews. Good naming, short functions that do one thing, etc. Read "Code complete" by Steve McConnell. This will increase the quality of your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. "Hacking" mistakes away
&lt;/h3&gt;

&lt;p&gt;If you find a bug in your code (an off-by-one mistake, for instance) do not try to hack your way into the correct code. Take a minute to read what you have written, not what you believe you have written. Jot down some small examples and try to come up with a solution from them. Be systematic. We assess this too, not just the end result.&lt;/p&gt;

&lt;h3&gt;
  
  
  14. Jumping straight into code
&lt;/h3&gt;

&lt;p&gt;Do &lt;strong&gt;NOT&lt;/strong&gt; jump straight into writing code.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Solve the problem "by hand".&lt;/li&gt;
&lt;li&gt;Explain your solution&lt;/li&gt;
&lt;li&gt;Analyze it (in Big O)&lt;/li&gt;
&lt;li&gt;Find bottlenecks and try to come up with something more efficient&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After all this, you can start coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Not managing space well enough
&lt;/h3&gt;

&lt;p&gt;The whiteboard is limited. Leave some space between lines so that you can erase and modify your code easily if you need to. You can draw lines indicating where the new code would fit if you are running out of space.&lt;/p&gt;

&lt;h3&gt;
  
  
  16. Asking for feedback at the end
&lt;/h3&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; ask for feedback at the end of your interview. Interviewers cannot give you the feedback (usually there are company policies to prevent this) and it gives a very bad impression: insecurity and inability to assess your performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Try to solve the following problems on your own. Here, I will not write a complete solution but I will show you my thought process. With a little practice, turning your ideas into code will be relatively easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Given an array of integers, return indices of the two numbers such that they add up to a specific target.&lt;br&gt;
You may assume that each input would have exactly one solution, and you may not use the same element twice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a very easy problem, but enough to focus on the process. Things that come to mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The input is an &lt;em&gt;array of integers&lt;/em&gt; 
a. Is it sorted?
b. What if it contains repeated elements? 
c. What if it contains negative elements? 
d. What if all the elements are negative/positive? 
e. What if the array is empty?
f. How big is it?&lt;/li&gt;
&lt;li&gt;Return &lt;em&gt;indices&lt;/em&gt;
a. What if there is no solution? 
b. What if there are multiple solutions?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You would need to ask some questions to the interviewer to clarify the most relevant points here. The questions about the array are pretty generic, created to make you think. In some cases, you may want to ask about the sign of the elements, if they are unique or repeated and if it is sorted. In other cases, ask what happens if the input is invalid - you may want to throw an exception or at least mention it even if you don't write the code for it.&lt;/p&gt;

&lt;p&gt;Regarding the output, you need to clarify what happens if there is no solution and if there is more than one. &lt;/p&gt;

&lt;p&gt;There are different approaches to this problem, with different time complexities. If you get stuck, try to mentally go through algorithms and data structures and see if they could help.&lt;/p&gt;

&lt;p&gt;Usually sorting and hash tables can simplify many problems. This is one of them.&lt;/p&gt;

&lt;p&gt;You can find the solution &lt;a href="https://leetcode.com/problems/two-sum/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thoughts:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Count&lt;/em&gt; the number of islands. I need a counter (obvious)&lt;/p&gt;

&lt;p&gt;2d grid map:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can I model this as a graph? I know  &lt;a href="https://en.wikipedia.org/wiki/Breadth-first_search"&gt;BFS&lt;/a&gt;  and  &lt;a href="https://en.wikipedia.org/wiki/Depth-first_search"&gt;DFS&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Islands are connected horizontally (same row) or vertically (same column), not diagonally&lt;/li&gt;
&lt;li&gt;I can only visit an island once, so I need some mechanism to avoid counting the same island twice. For instance, change the '1's to '0's (be it in the matrix we receive or in a copy we create if we can't modify the input) or a hash set where you store a pair of indices that define visited cells. I would go for the first option, but the second one is good to know since it can be used in other problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After having these two pieces of information, it is just a matter of turning that into code. Choosing between DFS or BFS is something you want to discuss with your interviewer, depending on the constraints of the problem. If you can choose, DFS is shorter.&lt;/p&gt;

&lt;p&gt;Make sure you consider the case of an empty matrix, a matrix full of ‘0’ - zero islands-, full of ‘1’ - just 1 island- and other test cases. What happens If you see a ‘2’ when you’re scanning the matrix? This is also something to discuss with your interviewer, like any other assumption. In case of doubt, it is better to overcommunicate your thoughts.&lt;/p&gt;

&lt;p&gt;You can find the solution &lt;a href="https://leetcode.com/problems/number-of-islands/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you have seen, there is little code here. This is because writing the code only comes after thinking and analyzing the problem. Turning it into code is &lt;em&gt;kind of the easy part&lt;/em&gt; (it obviously varies from problem to problem). Also, you can see how I’ve followed the process described in the last section: clarify the problem, come up with solutions, communicated with the imaginary interviewer, thought of edge cases, etc. This is what you should do until it becomes second nature.&lt;/p&gt;

&lt;p&gt;Prepare, be systematic, and patient. It is a lot of work to prepare for these interviews, but in life anything worth having requires effort.&lt;/p&gt;

&lt;p&gt;PS: I hope you found this useful. If so, like and share this article, visit my blog &lt;a href="https://www.yourdevopsguy.com"&gt;www.yourdevopsguy.com&lt;/a&gt;, and let's connect on &lt;a href="https://twitter.com/CodingLanguages"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>sql</category>
      <category>python</category>
    </item>
  </channel>
</rss>
