<?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: Archdemon</title>
    <description>The latest articles on DEV Community by Archdemon (@archdemondeveloper).</description>
    <link>https://dev.to/archdemondeveloper</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%2F1260676%2F904576d8-0c70-41c5-bf85-29fa52acef56.jpeg</url>
      <title>DEV Community: Archdemon</title>
      <link>https://dev.to/archdemondeveloper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/archdemondeveloper"/>
    <language>en</language>
    <item>
      <title>Roman Numerals in Go: The Self‑Correcting One‑Pass Trick</title>
      <dc:creator>Archdemon</dc:creator>
      <pubDate>Wed, 17 Dec 2025 15:05:16 +0000</pubDate>
      <link>https://dev.to/archdemondeveloper/roman-numerals-in-go-the-self-correcting-one-pass-trick-43oh</link>
      <guid>https://dev.to/archdemondeveloper/roman-numerals-in-go-the-self-correcting-one-pass-trick-43oh</guid>
      <description>&lt;p&gt;Today we’ll look at a classic interview problem: &lt;strong&gt;converting a Roman numeral to an integer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be honest, this is not something most of us use in real life. In 10+ years of programming, I haven’t needed it once. But it &lt;em&gt;does&lt;/em&gt; show up in interviews, and more importantly, it’s a great problem for learning how to reason about algorithms instead of memorising tricks.&lt;/p&gt;

&lt;p&gt;Let’s take it step by step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding the Problem
&lt;/h2&gt;

&lt;p&gt;You’re given a string made up of Roman numeral characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I, V, X, L, C, D, M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each character has a fixed numeric value:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;I = 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;V = 5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X = 10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L = 50&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C = 100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D = 500&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M = 1000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your task is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Convert the Roman numeral string into its integer value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem guarantees that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the input is always valid&lt;/li&gt;
&lt;li&gt;you don’t need to worry about malformed Roman numerals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That lets us focus entirely on the logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Straightforward (Brute‑Force) Approach
&lt;/h2&gt;

&lt;p&gt;The most natural way to solve this is to lean directly on the Roman numeral rules.&lt;/p&gt;

&lt;p&gt;Some pairs are &lt;em&gt;special&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IV = 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IX = 9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XL = 40&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XC = 90&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CD = 400&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CM = 900&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else is just addition.&lt;/p&gt;

&lt;p&gt;So a brute‑force approach looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Walk through the string from left to right&lt;/li&gt;
&lt;li&gt;If the current character and the next character form a subtractive pair, add that value and skip both&lt;/li&gt;
&lt;li&gt;Otherwise, add the value of the current character and move on&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works. It’s clear. And for this problem, it’s completely acceptable.&lt;/p&gt;

&lt;p&gt;But there’s a small cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you have to explicitly encode all subtractive pairs&lt;/li&gt;
&lt;li&gt;you need lookahead (&lt;code&gt;i + 1&lt;/code&gt;), which adds branching and edge checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, it’s reasonable to pause and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can we do this in a single pass, without treating some cases as special?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question leads to a more interesting solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Idea
&lt;/h2&gt;

&lt;p&gt;Here’s the idea we’ll build everything on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Always add. Correct only when proven wrong.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Roman numerals follow two simple rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Values normally add&lt;/li&gt;
&lt;li&gt;If a smaller value appears before a larger one, the smaller value should be subtracted&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VI = 5 + 1 = 6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IV = 5 − 1 = 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XL = 50 − 10 = 40&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of handling these cases up front, we’ll assume everything adds — and fix things only when we realise that assumption was wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pause for a Moment
&lt;/h2&gt;

&lt;p&gt;Before looking at code, stop here and think about this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I always add values, how would I &lt;em&gt;undo&lt;/em&gt; a mistake when I later discover that a value should have been subtracted?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keep that question in mind. The answer is the key to the whole solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Invariant (This Is Everything)
&lt;/h2&gt;

&lt;p&gt;The algorithm relies on one simple invariant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;At the start of each iteration, the running total already includes the previous symbol exactly once.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything that follows is just a consequence of that statement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Correction Works
&lt;/h2&gt;

&lt;p&gt;Let’s walk through a concrete example: &lt;code&gt;"XL"&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: &lt;code&gt;'X'&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Value = &lt;code&gt;10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;There is no previous symbol yet&lt;/li&gt;
&lt;li&gt;We add &lt;code&gt;10&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running total:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing to fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: &lt;code&gt;'L'&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Value = &lt;code&gt;50&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The previous value was &lt;code&gt;10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;According to Roman rules, that &lt;code&gt;10&lt;/code&gt; should have been subtracted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here’s the important part:&lt;/p&gt;

&lt;p&gt;We already &lt;strong&gt;added&lt;/strong&gt; &lt;code&gt;10&lt;/code&gt; in the previous step.&lt;/p&gt;

&lt;p&gt;To correct this, we need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;remove the earlier &lt;code&gt;+10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;apply &lt;code&gt;-10&lt;/code&gt; instead&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s a net change of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-2 * previous_value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the update becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current_value - 2 * previous_value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which gives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;50 - 2*10 = 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add that to the running total:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 + 30 = 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why We Subtract the &lt;em&gt;Previous&lt;/em&gt; Value
&lt;/h2&gt;

&lt;p&gt;This part is subtle and important.&lt;/p&gt;

&lt;p&gt;We are &lt;strong&gt;not correcting the total&lt;/strong&gt;.&lt;br&gt;
We are &lt;strong&gt;correcting the contribution of the previous symbol&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;previous&lt;/code&gt; is just the numeric value of the symbol we saw last&lt;/li&gt;
&lt;li&gt;the running total already includes it once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why this line works even on the first iteration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current - 2*previous
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;previous&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, there’s nothing to correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Code (Go)
&lt;/h2&gt;

&lt;p&gt;Once the idea is clear, the code becomes very straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;romanToInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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;curr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&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;num&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'I'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'V'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'X'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'L'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'C'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'D'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="sc"&gt;'M'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why This Is a Good Interview Solution
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Single pass&lt;/li&gt;
&lt;li&gt;O(1) extra space&lt;/li&gt;
&lt;li&gt;No lookahead&lt;/li&gt;
&lt;li&gt;No special cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More importantly, it demonstrates that you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maintain a clear invariant&lt;/li&gt;
&lt;li&gt;make simple assumptions&lt;/li&gt;
&lt;li&gt;correct them cleanly when new information appears&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  One‑Sentence Mental Model
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“I always add the current value. If I later realise the previous value should have been subtracted, I undo it by subtracting it twice.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If that sentence makes sense, the solution will always make sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This problem isn’t really about Roman numerals.&lt;/p&gt;

&lt;p&gt;It’s about writing algorithms that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;start with a simple assumption&lt;/li&gt;
&lt;li&gt;stay linear and readable&lt;/li&gt;
&lt;li&gt;correct themselves when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you see it that way, the &lt;code&gt;2 * previous&lt;/code&gt; no longer feels clever, it feels inevitable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;My goal here was to help you actually &lt;strong&gt;understand&lt;/strong&gt; why this algorithm works and not just walk away with something to memorize.&lt;/p&gt;

&lt;p&gt;Once that idea clicks, implementing it in your favorite language becomes a fun little exercise.&lt;/p&gt;

&lt;p&gt;If this helped you see the problem differently, feel free to share it with someone who might enjoy the same “aha” moment. And if you have questions, feedback, or a different mental model altogether, drop a comment. Those conversations are half the fun.&lt;/p&gt;

&lt;p&gt;Happy coding 👋&lt;/p&gt;

</description>
      <category>programming</category>
      <category>algorithms</category>
      <category>go</category>
      <category>learning</category>
    </item>
    <item>
      <title>Majority Element: Easy Problem, Sneaky Insight</title>
      <dc:creator>Archdemon</dc:creator>
      <pubDate>Sun, 14 Dec 2025 14:35:29 +0000</pubDate>
      <link>https://dev.to/archdemondeveloper/majority-element-easy-problem-sneaky-insight-37p0</link>
      <guid>https://dev.to/archdemondeveloper/majority-element-easy-problem-sneaky-insight-37p0</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Majority Element&lt;/strong&gt; problem on LeetCode looks like one of those questions you expect to solve in two minutes and immediately forget about.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; an array of numbers&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; the number that appears &lt;strong&gt;more than &lt;code&gt;n/2&lt;/code&gt; times&lt;/strong&gt;&lt;br&gt;
(&lt;code&gt;n&lt;/code&gt; is the size of the array)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s it. No tricks hiding in the corner.&lt;/p&gt;

&lt;p&gt;LeetCode even tells you upfront:&lt;br&gt;
👉 &lt;em&gt;“The majority element always exists.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So your brain does the obvious thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Cool. I’ll just count.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;99% of the time, that’s exactly the right instinct.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Obvious Solution (And Why It’s Perfectly Fine)
&lt;/h2&gt;

&lt;p&gt;You loop through the array, count how many times each number appears, and return the one whose count is greater than &lt;code&gt;n/2&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input:  [1, 1, 2, 2, 2, 3, 3]
Counts: {1: 2, 2: 3, 3: 2}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;2&lt;/code&gt; appears more than half the time. Done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;majorityElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="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;nums&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;counts&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;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&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;k&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="c"&gt;// unreachable due to problem guarantee&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; &lt;code&gt;O(N)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Space:&lt;/strong&gt; &lt;code&gt;O(N)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This solution is clean, readable, and correct.&lt;/p&gt;

&lt;p&gt;In real life, you’d probably stop here, ship it, and move on.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Follow-Up That Changes the Mood
&lt;/h2&gt;

&lt;p&gt;Then LeetCode adds one extra line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Could you solve it in linear time and O(1) space?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Translation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Same problem. No hashmap.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where the problem quietly stops being trivial and starts testing how you &lt;em&gt;think&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⏸️ Pause Here
&lt;/h2&gt;

&lt;p&gt;Before reading further, I’d genuinely recommend pausing for a moment and thinking about this yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does &lt;em&gt;“more than half”&lt;/em&gt; actually guarantee?&lt;/li&gt;
&lt;li&gt;What information do you really need to keep around?&lt;/li&gt;
&lt;li&gt;If counting everything was forbidden, what would you track instead?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you already know the solution, wonderful read along for a fun mental model.&lt;br&gt;
If you don’t, that’s completely fine. It wasn’t obvious to me the first time either.&lt;/p&gt;

&lt;p&gt;When you’re ready, keep going.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Mental Model Instead of Math
&lt;/h2&gt;

&lt;p&gt;Let’s stop thinking in terms of arrays and counters for a second.&lt;/p&gt;

&lt;p&gt;Instead, imagine this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Teams, Players, and Rounds
&lt;/h2&gt;

&lt;p&gt;Think of each &lt;strong&gt;number&lt;/strong&gt; as a &lt;strong&gt;team&lt;/strong&gt;.&lt;br&gt;
Each occurrence of that number is a &lt;strong&gt;player&lt;/strong&gt; on that team.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are multiple teams&lt;/li&gt;
&lt;li&gt;One team has &lt;strong&gt;more than half of all players&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The game plays out in &lt;strong&gt;rounds&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rules of the Game
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In each round, one player steps forward&lt;/li&gt;
&lt;li&gt;If two different teams step forward, both players are eliminated&lt;/li&gt;
&lt;li&gt;Eliminated players never come back&lt;/li&gt;
&lt;li&gt;A team can only keep playing if it still has unused players&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the key part:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The outcome of a round doesn’t matter.&lt;br&gt;
What matters is &lt;strong&gt;who still has players left&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Inevitably Happens
&lt;/h2&gt;

&lt;p&gt;Smaller teams run out of players pretty quickly.&lt;br&gt;
Once they’re empty, they’re done.&lt;/p&gt;

&lt;p&gt;The majority team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loses players too&lt;/li&gt;
&lt;li&gt;Gets beaten&lt;/li&gt;
&lt;li&gt;Cancels others out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But because it started with &lt;strong&gt;more players than all the other teams combined&lt;/strong&gt;, it can never be eliminated completely.&lt;/p&gt;

&lt;p&gt;By the end:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either it’s the only team left&lt;/li&gt;
&lt;li&gt;Or it’s the only team that can still send a player&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That team is the majority element.&lt;/p&gt;

&lt;p&gt;No tricks.&lt;br&gt;
No luck.&lt;br&gt;
Just inevitability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Turning That Into Code
&lt;/h2&gt;

&lt;p&gt;Now let’s map that mental model back to code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;candidate&lt;/code&gt; → the team currently sending players&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; → how many more players that team has &lt;em&gt;relative to others&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you walk through the array:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;count == 0&lt;/code&gt;
→ pick the current number as the new team&lt;/li&gt;
&lt;li&gt;Same number again
→ that team sends another player (&lt;code&gt;count++&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Different number
→ two players clash and are gone (&lt;code&gt;count--&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re not tracking wins.&lt;br&gt;
You’re tracking &lt;strong&gt;who can still play&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Go Implementation (O(1) Space)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;majorityElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;nums&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;count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num&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;num&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; &lt;code&gt;O(N)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Space:&lt;/strong&gt; &lt;code&gt;O(1)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the problem guarantees a majority element, no second pass is needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trivia
&lt;/h2&gt;

&lt;p&gt;This algorithm was introduced by &lt;strong&gt;Robert S. Boyer&lt;/strong&gt; and &lt;strong&gt;J. Strother Moore&lt;/strong&gt;, and is known as the &lt;strong&gt;Boyer–Moore Voting Algorithm&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can think of it as a different way of running an election:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of counting every vote up front,&lt;/li&gt;
&lt;li&gt;candidates face off round by round,&lt;/li&gt;
&lt;li&gt;and you only keep track of who still has supporters left.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, the candidate who survives isn’t just popular —&lt;br&gt;
they’re mathematically guaranteed to be the majority.&lt;/p&gt;

&lt;p&gt;Less bookkeeping.&lt;br&gt;
Same result.&lt;br&gt;
Much more clever.&lt;/p&gt;




&lt;h2&gt;
  
  
  Side-by-Side Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Space&lt;/th&gt;
&lt;th&gt;Obvious?&lt;/th&gt;
&lt;th&gt;Interview Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HashMap counting&lt;/td&gt;
&lt;td&gt;O(N)&lt;/td&gt;
&lt;td&gt;O(N)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boyer–Moore voting&lt;/td&gt;
&lt;td&gt;O(N)&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The hashmap solution is &lt;strong&gt;practical&lt;/strong&gt;.&lt;br&gt;
The Boyer–Moore solution is &lt;strong&gt;conceptual&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Interviewers like the second one not because it’s “better”,&lt;br&gt;
but because it shows you can reason from &lt;strong&gt;constraints and guarantees&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: When Would You Actually Use This?
&lt;/h2&gt;

&lt;p&gt;By now, you might be wondering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“This is clever… but when would I ever use this instead of a hashmap?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s a fair question.&lt;/p&gt;

&lt;p&gt;The Boyer–Moore Voting Algorithm is &lt;strong&gt;not&lt;/strong&gt; a general-purpose replacement for counting. It shines only when a &lt;strong&gt;strong guarantee&lt;/strong&gt; exists.&lt;/p&gt;

&lt;p&gt;You usually reach for it when &lt;strong&gt;all three&lt;/strong&gt; of these are true:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You’re dealing with &lt;strong&gt;large or streaming data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;majority element is guaranteed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You want &lt;strong&gt;predictable, minimal memory usage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Streaming or One-Pass Data
&lt;/h3&gt;

&lt;p&gt;If data comes in as a stream (logs, events, messages), you may not want to store everything just to count it.&lt;/p&gt;

&lt;p&gt;Boyer–Moore lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;process elements one at a time&lt;/li&gt;
&lt;li&gt;keep constant memory&lt;/li&gt;
&lt;li&gt;stop at any point with a meaningful candidate&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Large Inputs and Performance-Sensitive Code
&lt;/h3&gt;

&lt;p&gt;Hashmaps aren’t just “memory”.&lt;/p&gt;

&lt;p&gt;They involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allocations&lt;/li&gt;
&lt;li&gt;resizing&lt;/li&gt;
&lt;li&gt;hashing&lt;/li&gt;
&lt;li&gt;cache misses&lt;/li&gt;
&lt;li&gt;garbage collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boyer–Moore avoids all of that. It’s fast, cache-friendly, and predictable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Memory-Constrained Environments
&lt;/h3&gt;

&lt;p&gt;In embedded systems or edge devices, even small data structures matter.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;O(1)&lt;/code&gt; space algorithm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;uses fixed memory&lt;/li&gt;
&lt;li&gt;behaves consistently&lt;/li&gt;
&lt;li&gt;fails less spectacularly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That simplicity is a feature.&lt;/p&gt;




&lt;h3&gt;
  
  
  When &lt;em&gt;Not&lt;/em&gt; to Use This Algorithm
&lt;/h3&gt;

&lt;p&gt;Just as important:&lt;/p&gt;

&lt;p&gt;Don’t use Boyer–Moore if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a majority element is &lt;strong&gt;not guaranteed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;you need exact frequencies&lt;/li&gt;
&lt;li&gt;you need top-K elements&lt;/li&gt;
&lt;li&gt;you care about distribution, not dominance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those cases, a hashmap or sorting is the right tool.&lt;/p&gt;




&lt;h3&gt;
  
  
  A Simple Rule of Thumb
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use Boyer–Moore when dominance matters&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Use a hashmap when distribution matters&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both are good tools. They just solve different problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;My goal here was to help you actually &lt;strong&gt;understand&lt;/strong&gt; why this algorithm works and not just walk away with something to memorize.&lt;/p&gt;

&lt;p&gt;Once that idea clicks, implementing it in your favorite language becomes a fun little exercise.&lt;/p&gt;

&lt;p&gt;If this helped you see the problem differently, feel free to share it with someone who might enjoy the same “aha” moment. And if you have questions, feedback, or a different mental model altogether, drop a comment. Those conversations are half the fun.&lt;/p&gt;

&lt;p&gt;Happy coding 👋&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>learning</category>
      <category>algorithms</category>
    </item>
  </channel>
</rss>
