<?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: Alex Kang</title>
    <description>The latest articles on DEV Community by Alex Kang (@alexhanbich).</description>
    <link>https://dev.to/alexhanbich</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%2F898645%2Fb51593bb-eb3f-4b62-a856-29185f40a8a2.png</url>
      <title>DEV Community: Alex Kang</title>
      <link>https://dev.to/alexhanbich</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexhanbich"/>
    <language>en</language>
    <item>
      <title>Dynamic Programming: Knapsack</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Tue, 16 Aug 2022 01:41:31 +0000</pubDate>
      <link>https://dev.to/alexhanbich/dynamic-programming-knapsack-12l4</link>
      <guid>https://dev.to/alexhanbich/dynamic-programming-knapsack-12l4</guid>
      <description>&lt;h2&gt;
  
  
  What is Knapsack?
&lt;/h2&gt;

&lt;p&gt;There are many ways to describe the problem, but my favorite is to describe it as a thief robbing a store:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine a thief robbing a store with a bag of some capacity. The thief sees many items, and each item has a different value and weight. If he can only take one of each item, which items should he take to maximize his profit?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Understanding the problem
&lt;/h3&gt;

&lt;p&gt;What are some ways to solve this problem?&lt;/p&gt;

&lt;p&gt;At first glance, the knapsack problem seems as if a greedy approach would be suitable. But, a greedy approach does not guarantee an optimal solution.&lt;/p&gt;

&lt;p&gt;Let's look at a case where the greedy approach does not find an optimal solution.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Value/Weight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;5.33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's solve the problem for a capacity of 4.&lt;/p&gt;

&lt;p&gt;Using the greedy approach, we would take item A since it has the highest value-weight ratio. After we take item A, we won't have space for other items.&lt;/p&gt;

&lt;p&gt;But the optimal solution is to take items B and C.&lt;/p&gt;

&lt;p&gt;This counterexample shows that the greedy approach is not always optimal. &lt;/p&gt;

&lt;p&gt;Can we solve knapsack with dynamic programming? Does the problem have the two dynamic programming properties?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving 0/1 Knapsack
&lt;/h2&gt;

&lt;p&gt;In the previous post we discussed that to solve dynamic programming problems, you need:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;the problem defined as relatable subproblems&lt;/li&gt;
&lt;li&gt;recurrence relation to relate the sub-solutions to the original solution&lt;/li&gt;
&lt;li&gt;base cases for the recurrence relation&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1. Problem as relatable subproblems
&lt;/h3&gt;

&lt;p&gt;Let's identify the dynamic programming characteristics of the problem. Then, we can check if we can use dynamic programming.&lt;/p&gt;

&lt;h4&gt;
  
  
  Defining subproblems
&lt;/h4&gt;

&lt;p&gt;In the knapsack problem, we can choose to take or leave the item if the item fits into our knapsack. We need two variables to identify each choice (subproblem): the &lt;strong&gt;item index&lt;/strong&gt; and the &lt;strong&gt;remaining capacity&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Variable definitions:&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;code&gt;i&lt;/code&gt;: item index&lt;br&gt;
&lt;code&gt;rc&lt;/code&gt;: remaining capacity&lt;br&gt;
&lt;code&gt;i_weight&lt;/code&gt;: current item weight&lt;br&gt;
&lt;code&gt;i_val&lt;/code&gt;: current item value&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can define the subproblems to be &lt;code&gt;state(i, rc)&lt;/code&gt;. The collection of subproblems is all instances of &lt;code&gt;state(i, rc)&lt;/code&gt; where &lt;code&gt;0 &amp;lt;= i &amp;lt; num_items&lt;/code&gt; and &lt;code&gt;0 &amp;lt; rc &amp;lt;= total_capacity&lt;/code&gt;. The solution to each subproblem is the maximum profit  at &lt;code&gt;state(i, rc)&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Optimal substructure
&lt;/h4&gt;

&lt;p&gt;Can we construct the solution to &lt;code&gt;state(i, rc)&lt;/code&gt; using smaller subproblems?&lt;/p&gt;

&lt;p&gt;At item &lt;code&gt;i&lt;/code&gt;, we have two choices: to include &lt;code&gt;i&lt;/code&gt;, or to exclude &lt;code&gt;i&lt;/code&gt;. If we choose to exclude &lt;code&gt;i&lt;/code&gt;, the solution does not change from the previous item. If we choose to include &lt;code&gt;i&lt;/code&gt;, we need to make room for the item weight and include the item. The larger of the two is the solution to &lt;code&gt;state(i, rc)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Solution to &lt;code&gt;state(i, rc)&lt;/code&gt; is the maximum of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;state(i-1, rc)&lt;/code&gt; (exclude item &lt;code&gt;i&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state(i-1, rc-i_weight) + i_val&lt;/code&gt; (include item &lt;code&gt;i&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use smaller subproblems to find the optimal solution.&lt;br&gt;
So, the problem has the optimal substructure property.&lt;/p&gt;
&lt;h4&gt;
  
  
  Overlapping subproblems
&lt;/h4&gt;

&lt;p&gt;We need to calculate the subproblems &lt;code&gt;state(i-1, rc)&lt;/code&gt; and &lt;code&gt;state(i-1, rc-i_weight) + i_val&lt;/code&gt; in almost every state.&lt;/p&gt;

&lt;p&gt;So, the problem has the same subproblems, and the problem has the overlapping subproblems property.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Recurrence relation
&lt;/h3&gt;

&lt;p&gt;We already found the recurrence relation above!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...maximum of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;state(i-1, rc)&lt;/code&gt; (exclude item &lt;code&gt;i&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state(i-1, rc-i_weight) + i_val&lt;/code&gt; (include item &lt;code&gt;i&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finding the recurrence relation is usually the hardest part of the problem.&lt;br&gt;
Here are some tips for finding the recurrence relation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How can we use smaller subproblems to solve larger subproblems?&lt;/li&gt;
&lt;li&gt;Does the problem ask for the min/max of something? If so, the recurrence relation is often the min/max of a subset of subproblems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. Base cases for the recurrence relation
&lt;/h3&gt;

&lt;p&gt;When the problem is about finding the min/max of something, the base case value is usually 0.&lt;/p&gt;

&lt;p&gt;The base case is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When &lt;code&gt;i&lt;/code&gt; or &lt;code&gt;rc&lt;/code&gt; is out of range, we return 0.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Top-down approach
&lt;/h3&gt;

&lt;p&gt;A simple way to think about the top-down approach is "DFS + memoization". If we do not need to solve all subproblems linearly, a top-down approach can be more efficient than a bottom-up approach&lt;/p&gt;

&lt;p&gt;The three important parts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;function to solve a single subproblem&lt;/li&gt;
&lt;li&gt;DFS to traverse through the state-space tree&lt;/li&gt;
&lt;li&gt;data structure for memoization&lt;/li&gt;
&lt;li&gt;recurrence relation to relate the subproblems&lt;/li&gt;
&lt;li&gt;base cases for the recurrence relation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a solution with comments using python.&lt;/p&gt;


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


&lt;h4&gt;
  
  
  Time complexity for top-down approach
&lt;/h4&gt;

&lt;p&gt;Time complexity: O(NM) where N = num_items, M = capacity.&lt;br&gt;
Space complexity: O(NM) where N = num_items, M = capacity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bottom-up approach V1
&lt;/h3&gt;

&lt;p&gt;A simple way to think about the bottom-up approach is filling out the table. The bottom-up approach does not use recursion, so there is no recursion overhead.&lt;/p&gt;

&lt;p&gt;The important parts are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;table to keep to store solutions to subproblems (dimension = num_variable in each state)&lt;/li&gt;
&lt;li&gt;loop to fill out the table&lt;/li&gt;
&lt;li&gt;recurrence relation to relate the subproblems&lt;/li&gt;
&lt;li&gt;base cases for the recurrence relation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a solution with comments using python.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Time complexity for bottom-up approach V1
&lt;/h4&gt;

&lt;p&gt;Time complexity: O(NM) where N = num_items, M = capacity.&lt;br&gt;
Space complexity: O(NM) where N = num_items, M = capacity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bottom-up approach V2
&lt;/h3&gt;

&lt;p&gt;Can we reduce the space complexity? &lt;/p&gt;

&lt;p&gt;In the recurrence relation, we only access the previous and current row. We can use just two rows to solve knapsack.&lt;/p&gt;

&lt;p&gt;Here is a solution with comments using python.&lt;/p&gt;


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


&lt;h4&gt;
  
  
  Time complexity for bottom-up approach V2
&lt;/h4&gt;

&lt;p&gt;Time complexity: O(NM) where N = num_items, M = capacity.&lt;br&gt;
Space complexity: O(M) where M = capacity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bottom-up approach V3
&lt;/h3&gt;

&lt;p&gt;Can we reduce the space complexity even more?&lt;/p&gt;

&lt;p&gt;In the recurrence relation, we access the previous and current row. But, we only access columns to the left of the previous row. If we iterate the columns from the right, we can use a single row to solve knapsack.&lt;/p&gt;


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


&lt;h4&gt;
  
  
  Time complexity for bottom-up approach V3
&lt;/h4&gt;

&lt;p&gt;Time complexity: O(NM) where N = num_items, M = capacity.&lt;br&gt;
Space complexity: O(M) where M = capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing different methods
&lt;/h2&gt;

&lt;p&gt;To test my algorithms, I used the 8 test cases from &lt;a href="https://people.sc.fsu.edu/~jburkardt/datasets/knapsack_01/knapsack_01.html"&gt;here&lt;/a&gt;. Test 8 is a fairly large test case where num_item = 24 and capacity = 6404180.&lt;/p&gt;

&lt;p&gt;For fun, here is the execution time of each versions of knapsack.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Knapsack function&lt;/th&gt;
&lt;th&gt;Execution time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Top-down&lt;/td&gt;
&lt;td&gt;5.599s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bottom-up v1&lt;/td&gt;
&lt;td&gt;33.246s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bottom-up v2&lt;/td&gt;
&lt;td&gt;25.293s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bottom-up v3&lt;/td&gt;
&lt;td&gt;19.063s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason why the top-down approach is so fast is that the weights(each 6 digits) and the capacity(7 digits) are large.&lt;/p&gt;

&lt;p&gt;In this case, calculating for every single capacity is an overkill, since all weight values are 6 digits long.&lt;/p&gt;

&lt;p&gt;The difference between the execution time of the bottom-up approaches is most likely from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating different array sizes&lt;/li&gt;
&lt;li&gt;different number of conditionals&lt;/li&gt;
&lt;li&gt;unknown compiler optimizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know if you have any other ideas!&lt;/p&gt;

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

&lt;p&gt;Knapsack is a classic, but not an easy dynamic programming question. To solve dynamic programming questions, we need to identify the dynamic programming characteristics. When we identify them, we can find how the subproblems relate, and eventually lead to the recurrence relation.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dynamic Programming in Python</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Fri, 12 Aug 2022 07:01:00 +0000</pubDate>
      <link>https://dev.to/alexhanbich/dynamic-programming-in-python-5d9i</link>
      <guid>https://dev.to/alexhanbich/dynamic-programming-in-python-5d9i</guid>
      <description>&lt;h2&gt;
  
  
  What is dynamic programming?
&lt;/h2&gt;

&lt;p&gt;Dynamic programming is a technique that allows us to solve a class of problems with overlapping subproblems and optimal substructure. &lt;/p&gt;

&lt;p&gt;Dynamic programming is also a technique that trades space for time. With dynamic programming, a problem with exponential number of subproblems can often be solved in polynomial time.&lt;/p&gt;

&lt;p&gt;The time complexity of dynamic programming problems is usually O(MN), where M = number of subproblems, N = time complexity of subproblems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Characteristics of dynamic programming
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overlapping subproblem&lt;/strong&gt;: the original problem has multiple instances of the same subproblem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimal substructure&lt;/strong&gt;: the solution to the original problem can be constructed from solutions of subproblems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic programming implementations
&lt;/h3&gt;

&lt;p&gt;The two dynamic programming implementations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;top down (DFS + memoization)&lt;/li&gt;
&lt;li&gt;bottom up (tabulation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve dynamic programming problems, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the problem defined as relatable subproblems&lt;/li&gt;
&lt;li&gt;recurrence relation to relate the sub-solutions to the original solution&lt;/li&gt;
&lt;li&gt;base cases for the recurrence relation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common dynamic programming questions
&lt;/h2&gt;

&lt;p&gt;Here are 6 common dynamic programming questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knapsack&lt;/li&gt;
&lt;li&gt;Longest increasing subsequence&lt;/li&gt;
&lt;li&gt;Longest common subsequence (edit distance)&lt;/li&gt;
&lt;li&gt;Matrix chain multiplication&lt;/li&gt;
&lt;li&gt;Kadane's algorithm&lt;/li&gt;
&lt;li&gt;Distinct Ways&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>algorithms</category>
      <category>python</category>
    </item>
    <item>
      <title>Building a Second Brain</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Fri, 12 Aug 2022 05:22:05 +0000</pubDate>
      <link>https://dev.to/alexhanbich/building-a-second-brain-583f</link>
      <guid>https://dev.to/alexhanbich/building-a-second-brain-583f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Building a Second Brain: A Proven Method to Organize Your Digital Life and Unlock Your Creative Potential, by Tiago Forte&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I am personally not a fan of self-improvement books. Their advice sounds nice and sounds motivating, but in reality, it's really difficult to integrate the advice because it's out of context.&lt;/p&gt;

&lt;p&gt;This book is different because it teaches you a systematic way (the second brain) to apply that knowledge in your life.&lt;/p&gt;

&lt;p&gt;I'm not a note taker; it's harder to concentrate, and I barely ever looked at them. Plus, it takes forever to find the information you need even if you have all the notes in the world.&lt;/p&gt;

&lt;p&gt;Despite not liking note-taking, I found some great takeaways from this book that I want to incorporate into my life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Externalizing our thoughts makes them more concrete&lt;/li&gt;
&lt;li&gt;Organize our digital archive by "how actionable", not "what kind of info"&lt;/li&gt;
&lt;li&gt;Discoverability of info decreases as the amount of note-taking increases&lt;/li&gt;
&lt;li&gt;Distillation of notes increases discoverability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The author shares an amazing organization system called PARA, which stands for&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P: Projects (short-term goals you are working on)&lt;/li&gt;
&lt;li&gt;A: Areas (generalized long-term goals)&lt;/li&gt;
&lt;li&gt;R: Resources (future references)&lt;/li&gt;
&lt;li&gt;A: Archives (completed or inactive)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I organized my notes into PRA (without the 'Areas'), something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Project/
│   ├── Project1/
│   │   ├── somefile
│   ├── Project2/
│   │   ├── somefile
├── Resources/
│   ├── Topic1/
│   │   └── somefile
│   ├── Topic2/
│   │   └── somefile
└── Archives/
    └── archivefile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This book is a great read and contains a lot of information on how you can organize the massive amount of information you consume every single day. With the abundance of information, it has been harder to keep track of what we know and what we need. If you want to hear a solution to that problem, give this book a read!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Binary Search Templates in Python</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Fri, 12 Aug 2022 05:14:00 +0000</pubDate>
      <link>https://dev.to/alexhanbich/binary-search-template-in-python-44jo</link>
      <guid>https://dev.to/alexhanbich/binary-search-template-in-python-44jo</guid>
      <description>&lt;h2&gt;
  
  
  What is Binary Search?
&lt;/h2&gt;

&lt;p&gt;Binary search is a search algorithm that divides the search interval by half every time. That also means that the time complexity of binary search is O(log n)&lt;/p&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;Binary search can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;find single element in a sorted array&lt;/li&gt;
&lt;li&gt;find first index satisfying a condition&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Find single element in a sorted array
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&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="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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&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;while&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&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;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&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="mi"&gt;2&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&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;elif&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&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;mid&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;else&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;mid&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Find first index satisfying a condition
&lt;/h3&gt;

&lt;p&gt;Finding the first index satisfying a condition is the same as finding the first true value of a true-false array. &lt;br&gt;
ex: &lt;code&gt;[False, ... False, True, ... True]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;left and right should include and read &amp;amp; write space&lt;/li&gt;
&lt;li&gt;while loop halts when &lt;code&gt;left == right&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;after the while loop:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;left&lt;/code&gt; is the first index satisfying &lt;code&gt;condition() == True&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;left - 1&lt;/code&gt; is the last index satisfying &lt;code&gt;condition() == False&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&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="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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&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;while&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&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="mi"&gt;2&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&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;mid&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;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&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;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>algorithms</category>
      <category>python</category>
    </item>
    <item>
      <title>Two Pointers Templates in Python</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Fri, 12 Aug 2022 04:46:00 +0000</pubDate>
      <link>https://dev.to/alexhanbich/two-pointer-templates-in-python-349a</link>
      <guid>https://dev.to/alexhanbich/two-pointer-templates-in-python-349a</guid>
      <description>&lt;h2&gt;
  
  
  What is two pointers technique?
&lt;/h2&gt;

&lt;p&gt;Two pointer technique is using two pointers in an array to solve problems efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;3 common two pointers techniques are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sliding window&lt;/li&gt;
&lt;li&gt;Pointers from two ends&lt;/li&gt;
&lt;li&gt;Fast and slow pointers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sliding Window
&lt;/h3&gt;

&lt;p&gt;Sliding window can be used to search something in a subarray.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_counter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something_before&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something_after&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sliding_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# outer loop to move end index
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="c1"&gt;# start index only increase when condition
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;do_something_before&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;do_something_after&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pointers from two ends
&lt;/h3&gt;

&lt;p&gt;Pointers from two ends can be used when the problem can be reduced to finding two elements in an array that satisfy a condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition_left&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition_right&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pointers_from_two_ends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&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="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="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&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;while&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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="n"&gt;condition_left&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;left&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;if&lt;/span&gt; &lt;span class="n"&gt;condition_right&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fast and slow pointers
&lt;/h2&gt;

&lt;p&gt;Fast and slow pointers can be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect cycles&lt;/li&gt;
&lt;li&gt;remove duplicates&lt;/li&gt;
&lt;li&gt;find middle node
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast_slow_pointers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;slow&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;for&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="c1"&gt;# only move slow pointer when condition
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condition_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;slow&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>algorithms</category>
      <category>python</category>
    </item>
    <item>
      <title>DFS Templates in Python</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Fri, 12 Aug 2022 04:10:00 +0000</pubDate>
      <link>https://dev.to/alexhanbich/dfs-python-templates-4g7l</link>
      <guid>https://dev.to/alexhanbich/dfs-python-templates-4g7l</guid>
      <description>&lt;h2&gt;
  
  
  What is DFS?
&lt;/h2&gt;

&lt;p&gt;Depth-first Search (DFS) is a tree/graph traversal algorithm that explores as far as possible in each branch.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feie5ru67waobbezfnbmx.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feie5ru67waobbezfnbmx.png" alt="Example of a tree"&gt;&lt;/a&gt;&lt;br&gt;
DFS traversal of the tree above would be:&lt;br&gt;
&lt;code&gt;[0, 1, 3, 4, 2, 5 ,6]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DFS applications
&lt;/h2&gt;

&lt;p&gt;Some of the applications of DFS are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;traversing a explicit tree to find something&lt;/li&gt;
&lt;li&gt;traversing a graph to:

&lt;ul&gt;
&lt;li&gt;find topological sort of graphs&lt;/li&gt;
&lt;li&gt;cycle detection in graphs&lt;/li&gt;
&lt;li&gt;find spanning trees&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;use backtracking to:

&lt;ul&gt;
&lt;li&gt;solve puzzles&lt;/li&gt;
&lt;li&gt;solve combinatorial problems&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;We can simply traverse through the tree/graph using the following templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  DFS on binary tree
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&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="nf"&gt;do_something&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="nf"&gt;dfs&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;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;dfs&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;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  DFS on N-ary tree
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_children&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&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="nf"&gt;do_something&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;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_children&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="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  DFS on graphs
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;visited&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_neighbors&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs&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;visited&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nf"&gt;do_something&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;visited&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neighbor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;neighbor&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_neighbors&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="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neighbor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In addition to simple traversals, we can also pass value up from child to parent (using return value) or pass value down from parent to child (using function parameters).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of passing value up (return value)
&lt;/h3&gt;

&lt;p&gt;Finding max depth of N-ary tree&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_children&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;max_depth&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&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="mi"&gt;0&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_children&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;depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&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="nf"&gt;max_depth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&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;depth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Example of passing value down (function parameter)
&lt;/h3&gt;

&lt;p&gt;Print path on a binary tree&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs_path&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;res&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&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="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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="nf"&gt;dfs_path&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;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;dfs_path&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;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Backtracking is also a variation of DFS. Backtracking does not explore the whole tree/graph. Instead, backtracking stops exploring branches that cannot lead to a solution.&lt;/p&gt;

&lt;p&gt;Backtracking can often be used to solve puzzles or combinatorial problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backtracking template
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_children&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;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;backtrack&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nf"&gt;do_something&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;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_children&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="nf"&gt;backtrack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>algorithms</category>
      <category>python</category>
    </item>
    <item>
      <title>My Internship Experience</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Wed, 10 Aug 2022 03:02:24 +0000</pubDate>
      <link>https://dev.to/alexhanbich/my-internship-experience-3mdl</link>
      <guid>https://dev.to/alexhanbich/my-internship-experience-3mdl</guid>
      <description>&lt;p&gt;Hi, I'm a beginner on a software development journey with a passion for learning and development. Back in 2020, I was fortunate enough to intern with an amazing team of developers. Since then, I have been temporarily serving in the mandatory military in my country.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internship Experience
&lt;/h2&gt;

&lt;p&gt;The team that I was assigned to was responsible for developing and running messaging services in a microservice architecture.&lt;/p&gt;

&lt;p&gt;The team lead was my mentor, and he described briefly what microservices were and what their team was responsible for. My mentor often took extra time to explain more about the architecture and why the team made each design choice.&lt;/p&gt;

&lt;p&gt;My first job was to get familiar with the code base. Luckily, the team had some deprecation work. While I was doing deprecation work, I made my first ever pull request and also my first ever contribution to production code. I was also able to experience a little bit of DevOps by making sure that the pipeline ran successfully.&lt;/p&gt;

&lt;p&gt;After I got familiar with the code base, I was given a chance to code a message exchange interchange, which was responsible for delivering messages from source to destination in a microservices architecture. It was a lot of fun working with them and seeing my contributions deployed to production.&lt;/p&gt;

&lt;p&gt;Our team decided to migrate from Bitbucket and Jfrog Pipelines to Github and Azure Pipelines. I was also able to learn about CI/CD and experiment with various technologies.&lt;/p&gt;

&lt;p&gt;One of our team members was in charge of migrating the SFTP server from Sterling File Gateway to AWS. It was expected that running the server on AWS would be almost half the cost of the Sterling File Gateway. I worked on researching if certain things were available in AWS, and I also worked hands-on with AWS labmda for POC of the migration.&lt;/p&gt;

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

&lt;p&gt;I have learned so much in my short internship. Even th&lt;/p&gt;

&lt;p&gt;ough I was not able to dive deeper into the concepts and technologies that I worked with, I am extremely grateful that I was exposed to so many important concepts that were not taught in school.&lt;/p&gt;

&lt;p&gt;Before my internship, I thought programming was all about algorithms, data structures, networking, and databases. My internship opened my eyes to a whole new world of software development. I am excited about my journey to learn more and become a better software developer.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Solve it</title>
      <dc:creator>Alex Kang</dc:creator>
      <pubDate>Wed, 10 Aug 2022 00:41:00 +0000</pubDate>
      <link>https://dev.to/alexhanbich/how-to-solve-problems-4915</link>
      <guid>https://dev.to/alexhanbich/how-to-solve-problems-4915</guid>
      <description>&lt;p&gt;I have always wanted to become better at problem-solving, but I never had a concrete plan on how I could be better. &lt;/p&gt;

&lt;p&gt;I came across "How to Solve It" by G. Polya, written in 1945 by a mathematician who gave 4 simple steps to solve any type of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand the problem
&lt;/h2&gt;

&lt;p&gt;This step seems so trivial, but it is also easy to neglect the importance of it because it is trivial. I personally have tried to solve problems without fully understanding them. I wasted many hours developing a solution that did not solve the initial problem, or missed an easier way to solve the problem.&lt;/p&gt;

&lt;p&gt;To make sure you understand the problems, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do you understand all the words in the problem?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you restate the problem?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you visualize the problem?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the unknown?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is known?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the connection between the known and the unknown?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Devise a plan
&lt;/h2&gt;

&lt;p&gt;When we understand the problem, we need to come up with a plan to find the unknown. This step may take a long time!&lt;/p&gt;

&lt;p&gt;To come up with a plan, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do you know a related problem? Can you use it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you solve a related or smaller problem?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Carry out the plan
&lt;/h2&gt;

&lt;p&gt;Carrying out the plan is much easier than devising a plan. &lt;/p&gt;

&lt;p&gt;While carrying out your plan, you should check each step. If the plan does not work, go back to devising a plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Look back
&lt;/h2&gt;

&lt;p&gt;After you have solved the problem, it is important to look back and examine the solution. &lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can you check the result?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you derive the solution differently?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can you use the solution for some other problem?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Even though the steps are somewhat obvious, we often neglect these steps. I have known these steps for a while now, but I still don't spend enough time on the first two steps, just out of laziness or impatience. But in the end, lack of planning almost always leads to disaster. Follow these steps and focus on the first two steps to become better at problem solving.&lt;/p&gt;

</description>
      <category>books</category>
    </item>
  </channel>
</rss>
