<?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>Forem: Duncan McArdle</title>
    <description>The latest articles on Forem by Duncan McArdle (@duncanmcardle).</description>
    <link>https://forem.com/duncanmcardle</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%2F798497%2F53b10618-daa1-4f4d-b97e-ae0fce96331f.jpeg</url>
      <title>Forem: Duncan McArdle</title>
      <link>https://forem.com/duncanmcardle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/duncanmcardle"/>
    <language>en</language>
    <item>
      <title>What is LeetCode, and why do I post solutions to it on online?</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 16:22:52 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/what-is-leetcode-and-why-do-i-post-solutions-to-it-on-online-3bpn</link>
      <guid>https://forem.com/duncanmcardle/what-is-leetcode-and-why-do-i-post-solutions-to-it-on-online-3bpn</guid>
      <description>&lt;p&gt;A few months back, I entered the crazy world of &lt;a href="https://leetcode.com/"&gt;LeetCode&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is LeetCode
&lt;/h1&gt;

&lt;p&gt;For those of you who don’t know, LeetCode is a site that posts thousands of coding problems at varying difficulties, and asks you to solve them, whilst providing various test cases that your solution must pass. Additionally (and in my opinion most valuably), LeetCode also has a big community of users who share and comment on solutions to said problems.&lt;/p&gt;

&lt;p&gt;LeetCode’s most common user is someone seeking employment at one of the world’s biggest tech companies, all of whom utilise coding problems (AKA algorithmic coding) as a means of picking out the best candidates in the thousands of daily applicants they receive.&lt;/p&gt;

&lt;p&gt;Now, the rationale here isn’t that you need to be able to come up with complicated algorithmic solutions in order to work at Google or Facebook, but rather that by learning such algorithms and applying them whilst interviewing, you show that you’re willing to go above and beyond to get the job. It’s a bit like asking 100 people interviewing to be a chef to count to 1,000,000 — you may never actually need to do it, but by trying (and potentially succeeding), you’ve differentiated yourself from the rest of the applicants.&lt;/p&gt;

&lt;p&gt;Now that isn’t to say that you won’t ever use the kind of complex algorithms and data structures you find on LeetCode in the real world. In fact, there are some concepts, such as “Big O Notation”, that really can change your day-to-day work as an engineer. In addition, depending on the team you end up working in, graph traversal or LinkedList manipulation &lt;em&gt;may&lt;/em&gt; be as common a task as writing unit testing. These companies aren’t saying you &lt;em&gt;will&lt;/em&gt; use such methods during your time with them, but they want to know that if they need you to, you &lt;em&gt;can.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why would I want to share LeetCode solutions?
&lt;/h1&gt;

&lt;p&gt;To some, the act of posting a solution to a problem on the open internet may seem a little odd. It’s a bit like posting the answers to a test; yes readers will be able to answer the questions, but if they're asked an even slight variation of the original question, they’ll be stumped.&lt;/p&gt;

&lt;p&gt;But in reality, these problems rarely have a single correct answer. In fact, the process is typically more about identifying methods and applying concepts than it is arriving at a single correct solution. Even if you &lt;em&gt;do&lt;/em&gt; provide a perfect solution, and one that beats out every other submission in terms of timing, you still might find another solution in the comments that makes you say “Oh, that’s a &lt;em&gt;much&lt;/em&gt; better way of doing it!”.&lt;/p&gt;

&lt;p&gt;To give you a great example; &lt;a href="https://leetcode.com/problems/two-sum/"&gt;this LeetCode problem&lt;/a&gt; asks you to find all pairs of numbers in an array that add to a given number. The most obvious solution to me was to loop through the array twice (one inside the other), and add all possible pairs together. This solution worked, was pretty quick for the example case of 4 numbers, and was easy to understand. But lo and behold, my submission was incredibly slow compared to others, unusably so with a bigger dataset. So I quickly jumped into the discussion and found a method that’s infinitely better; (Hash)Maps! Now not only do I have a better solution to submit, but the next time I’m writing similar code in my day-to-day work, I stop and think; “Would a Map be better here?”. None of this would be possible without sharing solutions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why I started posting the solutions online
&lt;/h1&gt;

&lt;p&gt;So we’ve established what LeetCode is, as well as why you might share solutions for their problems. But why, you may be thinking, post them online?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Because the LeetCode discussion section is… meh
&lt;/h2&gt;

&lt;p&gt;Although a fantastic resource for finding solution and guidance, at the end of the day the “Discuss” tab on each LeetCode problem is a fairly typical, short-form post and reply system. The vast majority of responses are short, most submissions are uncommented and underexplained, and generally speaking the whole thing is geared more towards people who are already familiar with the process, and are looking to say “Oh that approach is a little better” rather than “How on earth do I even &lt;em&gt;start&lt;/em&gt; to solve this?”.&lt;/p&gt;

&lt;p&gt;Now, that isn’t to say that every discussion is like this. Some users go out of their way to take you through their solution step-by-step, some post video walkthroughs, and some just comment their code extensively. There are plenty of great posters on LeetCode who do not fit the description above.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Because it helps me learn (and not cut corners)
&lt;/h2&gt;

&lt;p&gt;When faced with a difficult problem on LeetCode, I will often (after staring at the wall for ~10 minutes) switch to the “Discuss” tab and start looking at solutions. If I’m lucky, I’ll soon have a working submission inspired by another poster, and can move onto the next problem.&lt;/p&gt;

&lt;p&gt;But the issue here, is that taking this shortcut often leads to under-understanding a solution. Instead of coming up with it organically, and understanding the full process from start to finish, I only really understand how the solution solves the problem (it’s a bit like saying “I know 2 + 2 = 4, but I don’t know &lt;em&gt;why&lt;/em&gt;”).&lt;/p&gt;

&lt;p&gt;The fix I have come up with to this issue is to write up my solutions in a way that can guide others from start to finish. What this means is that I have to be able to fully understand the solution, in a way that would have allowed me to solve it from scratch, and to a depth at which I am capable of explaining it to the next person in the chain.&lt;/p&gt;

&lt;p&gt;It is a strange situation where in order to understand something, I must be able to teach it to others, and I’ve found this really works for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Because I like writing
&lt;/h2&gt;

&lt;p&gt;As a long-time amateur writer, and frequent online poster on a variety of formats, I enjoy the act of writing. Typically this has been via fiction, but I’ve found it interesting explaining technical solutions in written form, and as per my point above, have found that writing it out aids my own understanding at the same time.&lt;/p&gt;

&lt;h1&gt;
  
  
  When will I stop?
&lt;/h1&gt;

&lt;p&gt;There are currently almost 2,000 problems on LeetCode. I’ll be surprised if I ever write up 10% of them, not least because beyond that point you’re often repeating the same approach in a slightly modified way.&lt;/p&gt;

&lt;p&gt;In truth; I’ll probably stop writing up LeetCode solutions when it stops benefitting me to do so, though it sounds a little selfish to put it that way, doesn’t it?&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>LeetCode problem #5 — Longest Palindromic Substring (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 16:05:18 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/leetcode-problem-5-longest-palindromic-substring-javascript-cfi</link>
      <guid>https://forem.com/duncanmcardle/leetcode-problem-5-longest-palindromic-substring-javascript-cfi</guid>
      <description>&lt;p&gt;In &lt;a href="https://leetcode.com/problems/longest-palindromic-substring/"&gt;this LeetCode challenge&lt;/a&gt; we’re asked to find the longest palindrome in a given string (a palindrome being a sequence of characters that is the same backwards as it is forwards, such as “bob”).&lt;/p&gt;

&lt;p&gt;Now you might be inclined to think that the solution to this is simply to look at every character, and then move outwards until the characters no longer mirror each other. However, whilst this would work for a string like “aba”, it would not work for a string like “abba”, so we need to look for mirrored characters both by individual letter, and by letter-couple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #1: Loop, call twice, and store globally
&lt;/h2&gt;

&lt;p&gt;Not a catchy title I know, but as this is my only real solution a catchy name seemed unnecessary!&lt;/p&gt;

&lt;p&gt;In this solution, we loop through all characters in the string, and for each one, we begin checking for palindromes both on the current character and on the current character-couple. For each palindrome found, we check if it’s the new longest one, and store it if so.&lt;/p&gt;


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


&lt;p&gt;This solution works great, and is pretty quick. In fact, the only way I’ve found to improve its performance is to replace the somewhat expensive string storing operations with pointer storage instead. In other words, instead of storing (and subsequently overwriting) the longest palindromes found each time, we instead store (and overwrite) pointers to the start and end of the longest palindrome. As you can imagine, once we get seriously long strings, this really starts to improve performance (at the cost of readability).&lt;/p&gt;


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


</description>
      <category>leetcode</category>
      <category>algorithms</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>LeetCode problem #4 — Median of two sorted arrays (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 16:02:38 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/leetcode-problem-4-median-of-two-sorted-arrays-javascript-10l0</link>
      <guid>https://forem.com/duncanmcardle/leetcode-problem-4-median-of-two-sorted-arrays-javascript-10l0</guid>
      <description>&lt;p&gt;In &lt;a href="https://leetcode.com/problems/median-of-two-sorted-arrays/"&gt;this LeetCode challenge&lt;/a&gt; we’re provided with two ordered arrays, and asked to find the median value.&lt;/p&gt;

&lt;p&gt;Just to clarify, the median is the &lt;strong&gt;middle&lt;/strong&gt; value. So for example, the median of the array &lt;code&gt;[1,2,3]&lt;/code&gt; would be 2. However, if there are an odd number of values, then the median is the average (mean) of the middle two values. So in an array of &lt;code&gt;[1,2,3,4]&lt;/code&gt; the median value is the average (mean) of 2 and 3, which is 2.5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #1: The power of JavaScript
&lt;/h2&gt;

&lt;p&gt;Okay, so this is kind of like cheating. With JavaScript, we can concatenate (combine) the arrays, sort them into ascending order, and then just pluck out the middle number(s). This makes things incredibly simple, but isn’t all that efficient:&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Solution #2: Looping to the middle
&lt;/h2&gt;

&lt;p&gt;I came up with this idea while trying to crack the “correct” approach (see below). Basically, we start by figuring out the middle point of the combined array, and then we loop towards that point, pulling in the lower value of each array as we do, 1 element at a time, until we reach the middle. Once we reach the middle, we know we’re at the median.&lt;/p&gt;


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


&lt;p&gt;This approach is actually really quite efficient (faster than 97% of JavaScript submissions at the time of writing), but isn’t particularly mathematical, which is what most submissions on LeetCode seem to suggest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #3: The “right” approach (binary searching)
&lt;/h2&gt;

&lt;p&gt;I’ll be honest and up front here: I do not like this solution at all. Despite being elegant and (eventually) understandable, it’s just not what good programming is to me. If I were to ask someone during an interview to solve this problem (which I would never do), I would be perfectly happy with them spending 5–10 minutes on providing me with either of the above two solutions. Watching them struggle for 45 minutes on this approach would have no value to me.&lt;/p&gt;

&lt;p&gt;As a matter of fact, even though I do now, after many hours, finally understand this approach, I just don’t see the point in me writing one out. Instead, this fantastic video will take you through the math behind it and provide some code, in far simpler terms than the “Solution” page on LeetCode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=LPFhl65R7ww"&gt;https://www.youtube.com/watch?v=LPFhl65R7ww&lt;/a&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>javascript</category>
      <category>programming</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>LeetCode problem #3 — Longest substring without repeating characters (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 16:00:11 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/leetcode-problem-3-longest-substring-without-repeating-characters-javascript-3omg</link>
      <guid>https://forem.com/duncanmcardle/leetcode-problem-3-longest-substring-without-repeating-characters-javascript-3omg</guid>
      <description>&lt;p&gt;In &lt;a href="https://leetcode.com/problems/longest-substring-without-repeating-characters"&gt;this LeetCode challenge&lt;/a&gt; we’re asked to find the length of the longest string of characters in a provided string that does not contain repeating characters. In other words, in the string &lt;code&gt;hello&lt;/code&gt; the longest substring without repeating characters is &lt;code&gt;hel&lt;/code&gt; (with a length of 3).&lt;/p&gt;

&lt;p&gt;The main method for solving this problem is with a “moving window”, and all of the below approaches use some form of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #1: Double-loop with a Set
&lt;/h2&gt;

&lt;p&gt;This was my first and by far least sophisticated method. In it, we loop once through all characters in the provided string, and then for each one we loop through the remaining characters, adding each one into a Set until we find a repeating character. At that point, we check if its the longest string found so far, and store its length if so. This repeats until the end of the string until we have found our longest substring.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Solution #2: Array
&lt;/h2&gt;

&lt;p&gt;This solution is similar to the above, but instead uses an array to store the running string, which has the benefit of being ordered, and having the &lt;code&gt;splice&lt;/code&gt; and &lt;code&gt;indexOf&lt;/code&gt; functionality that make this solution particularly easy on the eye and removes the need for the nested loop.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Solution #3: Map
&lt;/h2&gt;

&lt;p&gt;LeetCode user &lt;a href="https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/1979/Simple-Javascript-Code"&gt;nilath posted this great solution&lt;/a&gt; using a Map, which I have adjusted to improve readability. It takes the moving window concept but utilises Maps for lightning-fast lookups. Interestingly, because a Map is a key-value pair, we’re able to use the letter as the key, and the position that it sits within the string as the value:&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Solution #4: Set
&lt;/h2&gt;

&lt;p&gt;This solution was inspired by &lt;a href="https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/1812/Share-my-Java-solution-using-HashSet"&gt;jeantimex’s Java solution&lt;/a&gt;, and builds upon the Map concept but simplifies things slightly to use a Set instead. This has the benefit of reducing code complexity, but arguably damages readability:&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Comparing the solutions
&lt;/h2&gt;

&lt;p&gt;All approaches (excluding the double-loop) are of similar performance, and vary between tests enough to make them negligible:&lt;/p&gt;


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


&lt;p&gt;What is interesting however is that LeetCode’s processor is so optimised for array work that if you start all of these approaches by first converting the string to an array (using &lt;code&gt;string.split('')&lt;/code&gt;), you’ll see performance gains across the board.&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>javascript</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>LeetCode problem #2 — Add two numbers (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:58:28 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/leetcode-problem-2-add-two-numbers-javascript-510n</link>
      <guid>https://forem.com/duncanmcardle/leetcode-problem-2-add-two-numbers-javascript-510n</guid>
      <description>&lt;p&gt;In &lt;a href="https://leetcode.com/problems/add-two-numbers/"&gt;this LeetCode challenge&lt;/a&gt; we’re asked to add together two numbers. Seem simple? Well it isn’t. Of course, it’s &lt;em&gt;a lot&lt;/em&gt; simpler than the way it’s explained on the page, but I suppose that’s a matter of opinion… however I encourage you to read the official one first.&lt;/p&gt;

&lt;p&gt;Head hurting? Good stuff. Here’s my translation: Given two linked lists, which each represent a number in reverse order, add them together, and return the answer in the same format (a reverse-ordered linked list).&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #1: Converting the lists to numbers
&lt;/h2&gt;

&lt;p&gt;My very first instinct on this question was to convert the linked lists to their numerical counterparts, reverse them, add them together, convert the answer to a reverse-ordered linked list, and then return it. So here is what I came up with:&lt;/p&gt;


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


&lt;p&gt;First we establish a function to convert a reverse-ordered linked list into an array of digits, which we call &lt;code&gt;ConvertReverseListNodeToArray&lt;/code&gt;. What this function does, is that it takes a linked list, and recursively works its way through the list until it reaches the end, adding each value to an array as it goes. In addition, because we add each layer after the next layer in the list, we end up (intentionally) reversing the original order.&lt;/p&gt;

&lt;p&gt;Next up, we convert both lists using the above function, &lt;code&gt;.join()&lt;/code&gt; them into numbers, and add them together to get the numerical answer… which we must now convert back into a reverse-ordered linked list.&lt;/p&gt;

&lt;p&gt;First up on the back-stretch, we convert the total number to an array for easier traversal. Next we loop through the array, creating a ListNode for each number and adding it to an overall linked list. Once again, because of the order in which we’re doing this, the new list ends up being an (intentionally) reversed version of the original array.&lt;/p&gt;

&lt;p&gt;So there you have it, a somewhat straightforward and more mathematical approach to the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #2: While loop
&lt;/h2&gt;

&lt;p&gt;This approach is based on &lt;a href="https://leetcode.com/problems/add-two-numbers/discuss/1020/Javascript-solution"&gt;a solution posted by LeetCode user cosde&lt;/a&gt;. It works by running a while loop, which continues until all list elements have been traversed. On each iteration, it adds the two values together, checks if there’s a carry value (if the total exceeds 10), and if so passes it to the next iteration. Very elegant, and highly readable:&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Solution #3: Recursive function
&lt;/h2&gt;

&lt;p&gt;Another approach that I really liked was to use a recursive function with an optional parameter. This approach &lt;a href="https://leetcode.com/problems/add-two-numbers/solution/215253"&gt;was originally posted by anhduc130&lt;/a&gt;, with my only alterations being to improve readability. It’s similar to the while loop approach above, but… without the while loop!&lt;/p&gt;

&lt;p&gt;The way this approach works is that it makes use of JavaScript’s &lt;code&gt;arguments&lt;/code&gt; object, which contains all the arguments passed into a function, even if they weren’t specified in the function header. The reason this is important is that LeetCode already specify the function header, and this can’t be changed, but by using the arguments variable we’re able to get around this. Now, as has been posted in the comments to the above solution, there are potential edge-case issues with this approach, however it does pass on LeetCode, and looks really great:&lt;/p&gt;


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


&lt;p&gt;For each call of the function, it first adds the two ListNode’s values together (if they exist), as well as any value carried over from a previous run (again if it exists), and then calls the function again on the next level of the ListNodes (if &lt;em&gt;they&lt;/em&gt; exist), optionally passing a carry value to also be added in (if &lt;em&gt;that&lt;/em&gt; exists!).&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>javascript</category>
      <category>programming</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>LeetCode problem #1 — Two-sum (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:55:47 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/leetcode-problem-1-two-sum-javascript-4cb8</link>
      <guid>https://forem.com/duncanmcardle/leetcode-problem-1-two-sum-javascript-4cb8</guid>
      <description>&lt;p&gt;In &lt;a href="https://leetcode.com/problems/two-sum"&gt;this LeetCode challenge&lt;/a&gt; we’re asked to find two numbers in a given array which add up to make a specific number. So in other words, given the array &lt;code&gt;[1, 2, 3]&lt;/code&gt; and a target number of &lt;code&gt;5&lt;/code&gt; , we would return &lt;code&gt;[2, 3]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; We’re actually asked to return the indices of the numbers, not the numbers themselves, but the above made for a much simpler explanation!&lt;/p&gt;

&lt;p&gt;This challenge has a variety of solutions, and all revolve more or less around the same concept: For each number in the provided array, check if the complement to each number exists, and if so return the number and its complement.&lt;/p&gt;

&lt;p&gt;Wondering what the complement is? In this case, it means “The number that, when added to the current number, makes the target number”. So for example, if you have 3 and need 5, your complement will be 2, because 5 - 3 = 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 1: Nested for loop
&lt;/h2&gt;

&lt;p&gt;Here’s a super straightforward example used a nested loop:&lt;/p&gt;


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


&lt;p&gt;In this example we loop through all of the numbers, and then for each number, we once again loop through all of the numbers (excluding the first one, as the question states we cannot use the same number twice), and check if the second number is the required complement to the first one.&lt;/p&gt;

&lt;p&gt;This solution works fine, but nested loops like this are slow and generally frowned upon, so let’s look at some other approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 2: Maps
&lt;/h2&gt;


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


&lt;p&gt;In this example we declare an empty Map and then loop through the array of numbers. For each number, we check if the required complement exists in the Map, returning both numbers if so, or we add the current number into the Map. By the time the loop has reached the end of the array, we then have a map of all values provided (assuming the solution hasn’t already been found).&lt;/p&gt;

&lt;p&gt;Maps are incredibly quick for looking up data, so this solution is much faster than the nested for loop approach, but surprisingly it’s not the most common solution I see to this type of answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 3: HashMap / Object lookups
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In JavaScript, Objects are &lt;em&gt;not&lt;/em&gt; straight up HashMaps, but they’re often referred to as such.&lt;/p&gt;


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


&lt;p&gt;In what is a near-identical solution to the Map approach, this method stores the numbers one-by-one in an object, which then allows the program to lookup the value using an object key, rather than looping. This means that — again similar to Maps — we can look up our complement, rather than looping through all of the data to find it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing the solutions
&lt;/h2&gt;

&lt;p&gt;In reality, both the Map and Object solutions are very similar in terms of performance, and this shows when benchmarking the approaches:&lt;/p&gt;


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


&lt;p&gt;The actual performance of Maps vs Object lookups varies depending on a lot of things, and as JavaScript engines evolve to prioritise one or the other, this will swing back and forth. The stats above are taken directly from LeetCode, and are based on the specific test cases they supply, so as always, your mileage may vary!&lt;/p&gt;

&lt;p&gt;One thing that &lt;em&gt;is&lt;/em&gt; clear though, is that a nested for loop is a very bad idea.&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>javascript</category>
      <category>programming</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Sorting algorithms 101</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:47:28 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/sorting-algorithms-101-1d7b</link>
      <guid>https://forem.com/duncanmcardle/sorting-algorithms-101-1d7b</guid>
      <description>&lt;p&gt;In the world of programming, there are many ways to sort data. For the average engineer, you might just use &lt;code&gt;.sort()&lt;/code&gt;, perhaps with a slightly modified sorting function to return your data in a specific way. But that’s probably about the most you do.&lt;/p&gt;

&lt;p&gt;If however you’ve ever taken an algorithms class, used LeetCode, or just dived down a little deeper into sorting performance of a platform, you’ve probably heard of sorting algorithms.&lt;/p&gt;

&lt;p&gt;Now, make no mistake, your favourite language’s &lt;code&gt;.sort()&lt;/code&gt; (or equivalent) already uses one of these algorithms. In fact, if we’re being honest, it probably uses it in a way that’s faster than what you’re going to write anyway. But that doesn’t mean you won’t occasionally come up against a situation where writing a custom-sorting algorithm wouldn’t benefit you.&lt;/p&gt;

&lt;p&gt;So, in this article, I’m going to give a quick overview of the most common sorting-algorithms out there. Over time, I’ll be posting more implementation articles for sorting, and will add links to them here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stable vs unstable sorting
&lt;/h2&gt;

&lt;p&gt;Before we dive in, a quick note on stable and unstable sorting. In the sorting world, we’ll often come up against multiple instances of the same value. In the array &lt;code&gt;[1, 5, 7, 5, 3, 5]&lt;/code&gt; for example, we’ll encounter &lt;code&gt;5&lt;/code&gt; three times, and so our algorithm may be doing wasted work on comparing such values together and (potentially) rearranging them.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;stable&lt;/strong&gt; sort, our duplicate values will remain in their original order, with no time spent rearranging them for no reason.&lt;/p&gt;

&lt;p&gt;In an &lt;strong&gt;unstable&lt;/strong&gt; sort, our duplicate values will be rearranged, with time having been spent on this during the sort.&lt;/p&gt;

&lt;p&gt;Below is an example of this, with letters added to the duplicate values to indicate the order pre and post-sort (these letters would not be in the real data and would thus have no bearing on the actual sort):&lt;/p&gt;

&lt;p&gt;Stable sort: &lt;code&gt;[1, 5a, 7, 5b, 3, 5c]&lt;/code&gt; → &lt;code&gt;[1, 3, 5a, 5b, 5c, 7]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Unstable sort: &lt;code&gt;[1, 5a, 7, 5b, 3, 5c]&lt;/code&gt; → &lt;code&gt;[1, 3, 5c, 5a, 5b, 7]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Quick sort
&lt;/h2&gt;

&lt;p&gt;This algorithm relies on a simple premise; we sort a single value in an array of data, and then another one, and another one, until we sort the entire array. Each time we do this, we mark the now sorted point as a “pivot”, move all numbers &lt;em&gt;lower&lt;/em&gt; than it to its left, move all numbers &lt;em&gt;higher&lt;/em&gt; than it to its right, and then repeat the algorithm on either side of that point.&lt;/p&gt;

&lt;p&gt;Quick sorts are great if you want to do an in-memory sort, as we are constantly swapping existing data, but picking the “right” pivot point can be the difference between a fast and slow sort. In addition, this algorithm is an unstable one.&lt;/p&gt;

&lt;p&gt;This algorithm has a typical time complexity of O(n log n), but a worst-case of O(n²). The space complexity however is just O(log n).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;You can see my post on quick-sort implementations&lt;/em&gt; &lt;a href="https://dev.to/duncanmcardle/quick-sort-javascript-23hl"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Merge sort
&lt;/h2&gt;

&lt;p&gt;Here we split our to-be-sorted data into 2, right down the middle. Then, we run each half through the merge-sorting algorithm again, where it will be split recursively until we have just 2 pieces of data (1 on each side). From there, we re-combine each side in sorted order, until we eventually return to the top level with a sorted dataset.&lt;/p&gt;

&lt;p&gt;This algorithm is fast, but as it involves re-creating data and lots of moving around, its perhaps not as fast as some others. It is however highly customisable and a personal favourite of mine. Oh, and it’s a stable sort, too!&lt;/p&gt;

&lt;p&gt;Merge sorts have a time complexity of O(n log n), but a space complexity of O(n).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;You can see my post on merge-sort implementations&lt;/em&gt; &lt;a href="https://dev.to/duncanmcardle/merge-sort-javascript-2021"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Bucket sort
&lt;/h2&gt;

&lt;p&gt;In this algorithm, we divide our dataset into ordered buckets, sort each bucket, and then concatenate the buckets to give us a fully sorted set. This can make for a very elegant solution, especially if we pick the right number of buckets, however just like with quick-sort, picking the wrong number of buckets can slow things down significantly.&lt;/p&gt;

&lt;p&gt;It’s also worth mentioning that once we’ve split our data into buckets, we still have to sort each bucket. This may be done with a recursive bucket sort, or we may combine bucket sort with another algorithm (common implementations seem to involve combining bucket and insertion sorts).&lt;/p&gt;

&lt;p&gt;Bucket sorts can be fast if we pick the right number of buckets, and are also very easy to understand and implement. In addition, they are a stable sorting method.&lt;/p&gt;

&lt;p&gt;Bucket sorts have a typical time complexity of O(n + k) (where k is the number of buckets), but a worst case of O(n²). The space complexity if O(n*k) in the worst case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;GeeksforGeeks does a great 3 minute video on bucket sort&lt;/em&gt; &lt;a href="https://www.youtube.com/watch?v=VuXbEb5ywrU"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Bubble sort
&lt;/h2&gt;

&lt;p&gt;In this sorting algorithm, we are simply comparing values with their immediate neighbours. The way we do this is that we loop through the dataset, and we compare the value at &lt;code&gt;i&lt;/code&gt; with the value at &lt;code&gt;i + 1&lt;/code&gt; . If &lt;code&gt;i&lt;/code&gt; is higher, than we swap the two values and increment &lt;code&gt;i&lt;/code&gt;. After the first run, we will have identified the biggest value in the data, and moved it all the way to the right. Now on the next run, we will identify the second biggest value, and can ignore the already correctly placed value at the end of the array.&lt;/p&gt;

&lt;p&gt;Bubble sort is an easy and intuitive algorithm to implement. It performs the sort in-place, and is stable.&lt;/p&gt;

&lt;p&gt;In terms of complexity, the worst case for time is O(n²), however the space complexity is a wonderful O(1).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Michael Sambol does a great 2 minute video on bubble sort&lt;/em&gt; &lt;a href="https://www.youtube.com/watch?v=xli_FI7CuzA"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Insertion sort
&lt;/h2&gt;

&lt;p&gt;Much like with bubble sort, insertion sort loops through the values of an array, but this time it compares it with the number to its left. If the left-hand number is lower, then those two values are sorted (for now), and we move onto the next one. Once we find a value that is not lower than the one to its left, we loop through the values on its left until we can find (and place it in) its correct position.&lt;/p&gt;

&lt;p&gt;Insertion sort is once again a very easy algorithm to implement, and is also a stable one.&lt;/p&gt;

&lt;p&gt;For complexity, insertion sort has a worst-case time complexity of O(n²) (where the original data was presented in descending order and thus every value has to be swapped), but has a space complexity of O(1).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Michael Sambol does a great 2 minute video on insertion sort&lt;/em&gt; &lt;a href="https://www.youtube.com/watch?v=JU767SDMDvA"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And beyond
&lt;/h2&gt;

&lt;p&gt;There are a huge number of additional sorting algorithms out there, and I hope to add more to this article in the future.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>programming</category>
      <category>sorting</category>
    </item>
    <item>
      <title>Quick Sort (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:42:01 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/quick-sort-javascript-23hl</link>
      <guid>https://forem.com/duncanmcardle/quick-sort-javascript-23hl</guid>
      <description>&lt;p&gt;Quick sorting is a sorting algorithm that focuses on placing a single value of an array in its correct position for each iteration. It does this by splitting the array at a pivotal point (called the pivot), and then moving all numbers &lt;em&gt;greater than&lt;/em&gt; that pivot to be after it, and all numbers &lt;em&gt;less than&lt;/em&gt; the pivot to be before it.&lt;/p&gt;

&lt;p&gt;For example, given the array &lt;code&gt;[3, 7, 4, 5, 9]&lt;/code&gt;, you might select a pivot point of index 3 (which has a value of 4 in the above array). You would then go through each number and ask “Is it greater than or less than the pivot?”. In the above example, 3 would be less and so remain as-is. 7 would be greater and so be pushed beyond the pivot. 5 and 9 are then both greater and so remain where they are. So what we’re left with is an array of &lt;code&gt;[3, 4, 7, 5, 9]&lt;/code&gt;, where the pivot number (4) is now in the correct place in the array.&lt;/p&gt;

&lt;p&gt;From there, we can then repeat the process on the values either side of the array recursively, until every value in the array is correctly placed.&lt;/p&gt;

&lt;p&gt;In my opinion, quick sort isn’t a great method of sorting. There are far too many arbitrary aspects for how your code can work that make it less of an algorithm and more of an idea, and that makes implementation difficult to understand, as everyone has a slightly different method. In addition, it doesn’t resemble any real-life method of sorting, so I find it a little less intuitive than most. That said, most implementations do share key concepts, so if you can learn those, it makes everything a little bit easier.&lt;/p&gt;

&lt;p&gt;In addition, although not my favourite in terms of how it works, what I do like is that it performs the sorting operation in-memory, something you may sometimes be asked to do specifically.&lt;/p&gt;

&lt;p&gt;Below are two similar but different methods of implementing quick sort in JavaScript. Both follow the same pattern; we choose a pivot, split the array in 2 (one side with values less than the pivot, the other side with values greater than it), and then repeat the process for each part, until we eventually have a sorted array. Both also have the same final step; after sorting the non-pivot contents of the array, we then place the pivot in between both sides, so as to “correctly” place it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method #1: For loop
&lt;/h2&gt;

&lt;p&gt;In this method, we make our pivot our right-most element (so as to make the for loop more readable, as it can still go left-to-right). Then we loop through all of the elements in the array, and move those lower than the pivot to the left hand side, and those greater than it to the right hand side. Finally, we place the pivot in the middle of all these numbers (technically, we swap it for the lowest number that is greater than the pivot), and we have then found the correct placement for the pivot.&lt;/p&gt;


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


&lt;p&gt;This method was inspired by &lt;a href="https://www.youtube.com/watch?v=COk73cpQbFQ"&gt;this great video from mycodeschool&lt;/a&gt;, which I recommend you check out once you grasp the above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method #2: While
&lt;/h2&gt;

&lt;p&gt;In this method, we make our pivot the left-most element. Next we place markers at the next element in the array, and the final element of the array. Now, we move the left-marker right until we find a value that is greater than the pivot, and we move the right-marker left until we find a value that is lower than the pivot. In other words, we constrict the window of observation until we find numbers that belong on the opposite sides. Then we swap these values, so that they are now on the correct sides, and then continue until our markers meet. Finally, we place the pivot in the middle of all these numbers, and we have then found the correct placement for the pivot.&lt;/p&gt;


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


&lt;p&gt;This method was inspired by &lt;a href="https://www.youtube.com/watch?v=7h1s2SojIRw"&gt;this great video from Abdul Bari&lt;/a&gt;, which I recommend you check out once you grasp the above.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>javascript</category>
      <category>programming</category>
      <category>sorting</category>
    </item>
    <item>
      <title>Merge Sort (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:39:11 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/merge-sort-javascript-2021</link>
      <guid>https://forem.com/duncanmcardle/merge-sort-javascript-2021</guid>
      <description>&lt;p&gt;Sorting data is a notoriously slow process. In real life, if you’re given a list of 10 numbers and asked to sort it, you’ll probably first look through all the numbers for the lowest one, then you’ll look through them again for the next lowest, and you’ll repeat this process until you’ve covered everything.&lt;/p&gt;

&lt;p&gt;A lot of the time in code, it’s a similar story. You’ll loop through the numbers, and then for each number, you’ll compare it with all of the other numbers. Slow and inefficient.&lt;/p&gt;

&lt;p&gt;Enter “merge sort”, a concept where we split our to-be-sorted data in two, sort each half, and then merge those two halves together.&lt;/p&gt;

&lt;p&gt;Now, that probably doesn’t sound terribly intuitive at first. After all, we’re still having to sort each half, so how is that any easier? Well, the key differentiator is that we actually &lt;em&gt;keep&lt;/em&gt; splitting our data in half until we have just 2 elements, at which point, we simply compare them to each other in order to sort them.&lt;/p&gt;

&lt;p&gt;So let’s imagine we now have two sorted halves. Well, rather than loop through every possible number like we originally had to, we now only ever need to compare the &lt;em&gt;lowest number&lt;/em&gt; of each half. For example, if we have sorted arrays of &lt;code&gt;[1, 4, 6, 7]&lt;/code&gt; and &lt;code&gt;[2, 3, 5, 8]&lt;/code&gt;, we can merge them together by saying “Is 1 smaller than 2? Yes, so use 1. Is 4 smaller than 2? No, so use 2. Is 4 smaller than 3? No, so use 3” until we eventually end up with a sorted, merged array of numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some code
&lt;/h2&gt;

&lt;p&gt;Let’s look at a practical example of merge sort code. In this fairly classic implementation (which has been drawn out a little to aid readability), we recursively split our array in half, until we can no longer split it (only a single element remains). Once we reach that point, we begin backtracking up our recursive calls, and at each stage we then merge the split halves together, until we’re all the way back at the top, with a merged, sorted version of our original array.&lt;/p&gt;


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


&lt;p&gt;Let’s run through this flow with an array of &lt;code&gt;[1, 5, 3, 8, 4, 2, 9, 6]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, we’ll split it in half, to get our left-hand side of &lt;code&gt;[1, 5, 3, 8]&lt;/code&gt;. Now as that’s still too many elements, we’ll split it again to &lt;code&gt;[1, 5]&lt;/code&gt;, and again to get &lt;code&gt;[1]&lt;/code&gt; and &lt;code&gt;[5]&lt;/code&gt;. Now that we’ve sufficiently split down our first contenders, let’s compare them. We see that 1 is less than 5, so we return the merged and sorted array of &lt;code&gt;[1, 5]&lt;/code&gt;. Similarly, we also compare the next pair of 3 and 8, and return &lt;code&gt;[3, 8]&lt;/code&gt;, so it’s time for our first merge.&lt;/p&gt;

&lt;p&gt;We’ll declare a new array, and then compare each side’s first values; 1 and 3. We know 1 is lower, so we’ll remove 1 from the left-hand side and put it into the new array. So at this point, we have a left-hand side of &lt;code&gt;[5]&lt;/code&gt; , a right-hand side of &lt;code&gt;[3, 8]&lt;/code&gt; and a new array of &lt;code&gt;[1]&lt;/code&gt;. Comparing the next set of values (5 and 3), we can see that 3 is lower, so we remove that and add it to the new array. We now have a left array containing only 5, a right array containing only 8, and a new array of &lt;code&gt;[1, 3]&lt;/code&gt;. So we now compare 5 and 8, see that 5 is lower, and so remove that and put it on the new array to give us &lt;code&gt;[1, 3, 5]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point, because our left array is empty, we can save time by simply appending what remains of our right array onto the new array, as we know those numbers will be higher than all of the existing numbers in the new array. By doing this, we add our last remaining number of 8 to our new array, to give us &lt;code&gt;[1, 3, 5, 8]&lt;/code&gt;, a merged and sorted array.&lt;/p&gt;

&lt;p&gt;As the call stack moves upward, we’ll then repeat this process with the right-hand side, giving us a sorted array of &lt;code&gt;[2, 4, 6, 9]&lt;/code&gt;, and then merge-sort the two arrays together, using the aforementioned method, to get &lt;code&gt;[1, 2, 3, 4, 5, 6, 8, 9]&lt;/code&gt;, a merged and sorted version of the original array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing out
&lt;/h2&gt;

&lt;p&gt;Merge-sorting requires a number of key concepts to be understood before you can fully understand the approach, the most important of which is recursion. But once you have a good understanding of recursion, the rest should start to make sense.&lt;/p&gt;

&lt;p&gt;If however you’d like a little more help, I found &lt;a href="https://www.youtube.com/watch?v=TzeBrDU-JaY"&gt;this video from mycodeschool&lt;/a&gt; around the theory of merge-sorting to be a really helpful one, especially as it visualises how the data is manipulated at each individual stage.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>javascript</category>
      <category>programming</category>
      <category>sorting</category>
    </item>
    <item>
      <title>Binary search (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:36:57 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/binary-search-javascript-4gm2</link>
      <guid>https://forem.com/duncanmcardle/binary-search-javascript-4gm2</guid>
      <description>&lt;p&gt;Searching through data is painful, whether it’s in a database, a spreadsheet, or even on a piece of paper. Even in code, searching data tends to be a fairly slow process, at least when compared to other programmatic actions you might be carrying out.&lt;/p&gt;

&lt;p&gt;The classic method of course is with a loop. To find data with a loop, we simply look through every element until we find what we're looking for. This sounds great in principle, and is probably similar to how we’d look through a list of data in real life, but it’s not terribly efficient. However, if the data is randomly inserted and unordered, there’s not much we can do about this.&lt;/p&gt;

&lt;p&gt;If on the other hand, the data &lt;em&gt;is&lt;/em&gt; sorted, this opens us up for some other options, the primary of which is a binary search. We can think of a binary search as a way of chopping the data to be searched in half, until we reach the answer. To continue the real life example; imagine you have a list of 1,000 forenames in alphabetical order, and you’re looking for the name John. Rather than go through every individual name looking for John, what if we instead looked at entry 500 first? Well, if entry 500 was Lucy, then we’d know our answer lies in the first 500 entries, and so we can discard entries 500–1,000. We’ve just discarded 500 entries in a single check, pretty efficient right? So now all we do is repeat this process, until we are eventually left with just 1 entry.&lt;/p&gt;

&lt;p&gt;To give a more practical example, consider this list of 10 names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Amy  
2. Amanda  
3. Bill  
4. John  
5. Lucy  
6. Mark  
7. Nancy  
8. Terry  
9. Viktor  
10. William
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let’s now try and search for Nancy. First off we’ll check entry 5 (Lucy), and see that our name comes after that, so we’ll discard the first half of the list and be left with the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6. Mark  
7. Nancy  
8. Terry  
9. Viktor  
10. William
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let’s check the middle point again; Terry. Well we know Nancy comes before Terry, so we’ll discard the latter section, leaving us with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6. Mark  
7. Nancy  
8. Terry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This time when we check the middle value, we get a match! We’ve found the answer with just 3 checks, instead of the 7 it would have taken for a conventional loop.&lt;/p&gt;

&lt;p&gt;More importantly, this approach scales. If we have a list of 10 entries and we’re looking for a value, we must do up to 10 checks. If we apply that same algorithm to 100,000,000 entries, we must do &lt;strong&gt;up to&lt;/strong&gt; 100,000,000 checks. If instead we utilise a binary search, we will only need to do around 27 checks, depending on the target and the exact approach we use. That’s a pretty significant saving!&lt;/p&gt;
&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;

&lt;p&gt;Let’s look at some of this in code. We’ll look at an ordered array of 10 numbers &lt;code&gt;[1, 3, 4, 7, 8, 12, 16, 17, 18, 20]&lt;/code&gt;, and search for a target number of &lt;code&gt;16&lt;/code&gt;. To achieve this, we’ll use the following binary search implementation:&lt;/p&gt;


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



&lt;p&gt;First off we’ll establish our middle index of 5, which gives us a value in the above array of 12. We then compare that with the target and realise that the number we’re looking for is higher. So, we discard the first half of the data by moving the left-cursor to the middle point plus 1 (as we know the value at the middle point is not the target, having just checked it). This then reduces the array values we’re checking to &lt;code&gt;[16, 17, 18, 20]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we’ll establish a new middle index of 2, which gives us a value in the new array of 18. We compare this with our target of 12 and see that it’s higher than our target, so we discard the second half of the new array, leaving us with &lt;code&gt;[16, 17]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next we pick a new middle index of 1, which gives us a value of 17, and see that this is still above our target value. So we chop off the right-side of the latest array and leave ourselves with &lt;code&gt;[12]&lt;/code&gt;, which is of course our answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further considerations
&lt;/h2&gt;

&lt;p&gt;It’s worth pointing out that the above implementation is just one, fairly classic implementation of a binary search. There are additional minor tweaks that can be done, such as using the full length of the array, or having a &lt;code&gt;left &amp;lt;= right&lt;/code&gt; check rather than &lt;code&gt;left &amp;lt; right&lt;/code&gt;. Some of these aid readability and personal understanding, others give very different results, but most follow the same basic concept and thus give the same performance.&lt;/p&gt;

&lt;p&gt;Where you are most likely to need to make these sorts of changes is when what you’re looking for is a little more complicated, such as when you need to find not just the first occurrence of a value, &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fduncan-mcardle.medium.com%2Fleetcode-problem-34-find-first-and-last-position-of-element-in-sorted-array-javascript-3b781254ea23"&gt;but the last occurrence of it&lt;/a&gt;, and thus need to do a right-biased search. Or maybe your data isn’t ordered quite the way you expect, and so &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fduncan-mcardle.medium.com%2Fleetcode-problem-33-search-in-rotated-sorted-array-javascript-71cb7f38b563"&gt;you need to account for that&lt;/a&gt;. In all cases, the fundamentals of a binary search remain the same, but the way in which you traverse the provided values may need to change slightly.&lt;/p&gt;

&lt;p&gt;Finally I’d also like to mention a recursive form of binary searching. Once again the principles remain the same, but instead of a while loop running after we shrink the window of inspection (by moving left and right pointers closer together), we simply re-call the function with the smaller window. Personally, I prefer the iterative approach, but I will include it here for completeness:&lt;/p&gt;


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


</description>
      <category>algorithms</category>
      <category>javascript</category>
      <category>programming</category>
      <category>sorting</category>
    </item>
    <item>
      <title>SOLID principle #5: Dependency Inversion (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:24:35 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/solid-principle-5-dependency-inversion-javascript-20c5</link>
      <guid>https://forem.com/duncanmcardle/solid-principle-5-dependency-inversion-javascript-20c5</guid>
      <description>&lt;p&gt;The dependency injection principle states that high level code should never depend on low level interfaces, and should instead use abstractions. It’s all about decoupling code.&lt;/p&gt;

&lt;p&gt;Not following? I don’t blame you, but it’s surprisingly simple.&lt;/p&gt;

&lt;p&gt;Let’s say we have a piece of software that runs an online store, and within that software one of the classes (&lt;code&gt;PurchaseHandler&lt;/code&gt;) handles the final purchase. This class is capable of charging the user’s credit card, and does so by using a PayPal API:&lt;/p&gt;


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


&lt;p&gt;The problem here is that if we change from PayPal to Square (another payment processor) in 6 months time, this code breaks. We need to go back and swap out our PayPal API calls for Square API calls. But in addition, what if the Square API wants different types of data? Or perhaps it wants us to “stage” a payment first, and then to process it once staging has completed?&lt;/p&gt;

&lt;p&gt;That’s bad, and so we need to abstract the functionality out instead.&lt;/p&gt;

&lt;p&gt;Rather than directly call the PayPal API from our payment page, we’ll instead create another class called &lt;code&gt;PaymentHandler&lt;/code&gt;. The interface for this class will remain the same no matter what underlying payment system we use, even if the two systems are completely different. We’ll still need to make changes to the &lt;code&gt;PaymentHandler&lt;/code&gt; interface if we change payment processor, but our higher level interface remains unchanged.&lt;/p&gt;


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


&lt;p&gt;Now you may be looking at this and thinking “but wait, that’s &lt;em&gt;way&lt;/em&gt; more code”, and you’d be right. Like many of the SOLID principles (and indeed OO principles in general), the objective is less about writing less code or writing it quicker, and more about writing &lt;em&gt;better&lt;/em&gt; code. The above change will save you days or maybe even weeks further down the line, in exchange for spending a few hours on it now.&lt;/p&gt;

</description>
      <category>solid</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>SOLID principle #4: Interface Segregation (JavaScript)</title>
      <dc:creator>Duncan McArdle</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:22:55 +0000</pubDate>
      <link>https://forem.com/duncanmcardle/solid-principle-4-interface-segregation-javascript-3j7a</link>
      <guid>https://forem.com/duncanmcardle/solid-principle-4-interface-segregation-javascript-3j7a</guid>
      <description>&lt;p&gt;The interface segregation principle states that an entity should never be forced to implement an interface that contains elements which it will never use. For example, a &lt;code&gt;Penguin&lt;/code&gt; should never be forced to implement a &lt;code&gt;Bird&lt;/code&gt; interface if that &lt;code&gt;Bird&lt;/code&gt; interface includes functionality relating to flying, as penguins (spoiler alert) cannot fly.&lt;/p&gt;

&lt;p&gt;Now, this functionality is a little more difficult to demonstrate using JavaScript, due to its lack of interfaces. However, we can demonstrate it by using composition.&lt;/p&gt;

&lt;p&gt;Composition is a subject all by itself, but I’ll give a very high level introduction: Instead of inheriting an entire class, we can instead add chunks of functionality to a class. Here’s an example that actually addresses the interface segregation principle:&lt;/p&gt;


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


&lt;p&gt;What this example does is to add the flying functionality (or interface) only to the class(es) that require it. This means that penguins won’t be given the ability to fly, whereas birds will.&lt;/p&gt;

&lt;p&gt;This is one method of adhering to the interface segregation principle, but it is a fairly rough example (as, once again, JavaScript doesn’t play well with interfaces).&lt;/p&gt;

</description>
      <category>solid</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
