<?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: Hommies</title>
    <description>The latest articles on Forem by Hommies (@hommies_fcbf2afe8ddb0c2a7).</description>
    <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7</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%2F3935048%2F4936ff25-ae04-441c-94d9-acce58982ad0.jpg</url>
      <title>Forem: Hommies</title>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hommies_fcbf2afe8ddb0c2a7"/>
    <language>en</language>
    <item>
      <title>LeetCode Solution: 13. Roman to Integer</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Thu, 21 May 2026 11:37:46 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-13-roman-to-integer-3ne5</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-13-roman-to-integer-3ne5</guid>
      <description>&lt;h1&gt;
  
  
  How to Conquer Roman Numerals: LeetCode #13 Explained Simply!
&lt;/h1&gt;

&lt;p&gt;Hey there, future coding superstar! 👋 Ever looked at Roman numerals and thought, "That's a cool system, but how would I code that conversion?" Today, we're diving into LeetCode problem #13, "Roman to Integer," a fantastic problem for beginners that teaches some core programming concepts.&lt;/p&gt;

&lt;p&gt;Let's unravel this ancient number system together and turn it into elegant Python code!&lt;/p&gt;




&lt;h2&gt;
  
  
  The Roman Numeral Mystery (Problem Explanation)
&lt;/h2&gt;

&lt;p&gt;Roman numerals use a set of seven symbols:&lt;/p&gt;

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

&lt;p&gt;Usually, they're written from largest value to smallest, and you just add them up. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;II&lt;/code&gt; = 1 + 1 = 2&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XII&lt;/code&gt; = 10 + 1 + 1 = 12&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XXVII&lt;/code&gt; = 10 + 10 + 5 + 1 + 1 = 27&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds simple, right? But here's the twist! There are &lt;strong&gt;six special cases&lt;/strong&gt; where a smaller numeral comes &lt;em&gt;before&lt;/em&gt; a larger one, and instead of adding, you &lt;strong&gt;subtract&lt;/strong&gt; it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;IV&lt;/code&gt; = 4 (5 - 1)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;IX&lt;/code&gt; = 9 (10 - 1)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XL&lt;/code&gt; = 40 (50 - 10)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XC&lt;/code&gt; = 90 (100 - 10)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CD&lt;/code&gt; = 400 (500 - 100)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CM&lt;/code&gt; = 900 (1000 - 100)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, your task is to take a Roman numeral string (like "MCMXCIV") and convert it into its integer equivalent (like 1994). The input string is guaranteed to be a valid Roman numeral within a certain range.&lt;/p&gt;

&lt;p&gt;Let's look at an example to clarify:&lt;br&gt;
&lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;s = "MCMXCIV"&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;1994&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;M&lt;/code&gt; = 1000&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CM&lt;/code&gt; = 900 (C before M means 1000 - 100)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XC&lt;/code&gt; = 90 (X before C means 100 - 10)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;IV&lt;/code&gt; = 4 (I before V means 5 - 1)
Total: 1000 + 900 + 90 + 4 = 1994&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The "Aha!" Moment (Intuition)
&lt;/h2&gt;

&lt;p&gt;The core challenge is handling those subtraction cases (&lt;code&gt;IV&lt;/code&gt;, &lt;code&gt;IX&lt;/code&gt;, etc.). How do we know whether to add or subtract a symbol's value?&lt;/p&gt;

&lt;p&gt;Think about it: when you see &lt;code&gt;IV&lt;/code&gt;, you process &lt;code&gt;I&lt;/code&gt; and then &lt;code&gt;V&lt;/code&gt;. The &lt;code&gt;I&lt;/code&gt; isn't added directly because it's followed by a &lt;em&gt;larger&lt;/em&gt; value (&lt;code&gt;V&lt;/code&gt;). If it was &lt;code&gt;III&lt;/code&gt;, each &lt;code&gt;I&lt;/code&gt; would be added because it's followed by a &lt;em&gt;smaller or equal&lt;/em&gt; value (&lt;code&gt;I&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This gives us a huge hint: &lt;strong&gt;we need to look at the next character!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If the current symbol's value is &lt;strong&gt;less than&lt;/strong&gt; the next symbol's value, it's a subtraction case. We should subtract the current symbol's value.&lt;/li&gt;
&lt;li&gt;  Otherwise (if the current symbol's value is greater than or equal to the next symbol's value), it's a standard addition case. We should add the current symbol's value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "look ahead" strategy is the key to solving this problem efficiently!&lt;/p&gt;


&lt;h2&gt;
  
  
  Your Step-by-Step Guide (Approach)
&lt;/h2&gt;

&lt;p&gt;Let's break down how we can implement this "look ahead" strategy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Lookup Table:&lt;/strong&gt; First things first, we need an easy way to get the integer value for each Roman symbol. A dictionary (or hash map) is perfect for this! It maps each Roman character to its integer value (&lt;code&gt;'I': 1&lt;/code&gt;, &lt;code&gt;'V': 5&lt;/code&gt;, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initialize Result:&lt;/strong&gt; We'll need a variable, let's call it &lt;code&gt;result&lt;/code&gt;, to keep a running total of our integer conversion. Start it at &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterate with a "Look Ahead":&lt;/strong&gt; We'll loop through the Roman numeral string. However, since we need to compare the current character with the &lt;em&gt;next&lt;/em&gt; one, we should stop our loop one character before the end of the string.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For each pair of &lt;code&gt;(current_char, next_char)&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;  Look up &lt;code&gt;current_char&lt;/code&gt;'s value (&lt;code&gt;val_current&lt;/code&gt;) in our dictionary.&lt;/li&gt;
&lt;li&gt;  Look up &lt;code&gt;next_char&lt;/code&gt;'s value (&lt;code&gt;val_next&lt;/code&gt;) in our dictionary.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Condition Check:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;val_current &amp;lt; val_next&lt;/code&gt; (e.g., 'I' is 1, 'V' is 5, so 1 &amp;lt; 5): This is a subtraction case! Add &lt;code&gt;-val_current&lt;/code&gt; to our &lt;code&gt;result&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Else (&lt;code&gt;val_current &amp;gt;= val_next&lt;/code&gt;): This is an addition case! Add &lt;code&gt;val_current&lt;/code&gt; to our &lt;code&gt;result&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handle the Last Character:&lt;/strong&gt; Our loop stops one character before the end. This means the very last character in the string was never compared as a &lt;code&gt;current_char&lt;/code&gt; to a &lt;code&gt;next_char&lt;/code&gt;. Since a last character can &lt;em&gt;never&lt;/em&gt; be part of a subtraction pair (it has no character &lt;em&gt;after&lt;/em&gt; it), its value is &lt;strong&gt;always added&lt;/strong&gt;. So, after the loop, we simply add the value of the &lt;code&gt;last_char&lt;/code&gt; to our &lt;code&gt;result&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return:&lt;/strong&gt; Finally, &lt;code&gt;result&lt;/code&gt; holds the complete integer conversion. Return it!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


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

&lt;p&gt;Here's the Python solution based on our approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;romanToInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Initialize our result accumulator
&lt;/span&gt;
        &lt;span class="c1"&gt;# Our handy lookup table for Roman symbols to integer values
&lt;/span&gt;        &lt;span class="n"&gt;roman_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;V&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;L&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;D&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;M&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Iterate through the string, comparing current character (a) with the next (b)
&lt;/span&gt;        &lt;span class="c1"&gt;# The zip(s, s[1:]) trick cleverly creates pairs:
&lt;/span&gt;        &lt;span class="c1"&gt;# (s[0], s[1]), (s[1], s[2]), ..., (s[N-2], s[N-1])
&lt;/span&gt;        &lt;span class="c1"&gt;# This processes all pairs *except* for the very last character s[N-1]
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;current_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]):&lt;/span&gt;
            &lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roman_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;current_char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;next_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roman_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next_char&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;current_value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;next_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# If current value is smaller than next, it's a subtraction case (e.g., IV, IX)
&lt;/span&gt;                &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;current_value&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Otherwise, it's a standard addition case (e.g., III, L)
&lt;/span&gt;                &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;current_value&lt;/span&gt;

        &lt;span class="c1"&gt;# After the loop, the value of the *last* character in the string
&lt;/span&gt;        &lt;span class="c1"&gt;# has not yet been added to `res`. It will always be an addition.
&lt;/span&gt;        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;roman_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Performance Check (Time &amp;amp; Space Complexity)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(N)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We iterate through the input string &lt;code&gt;s&lt;/code&gt; once using the &lt;code&gt;zip&lt;/code&gt; function, which effectively processes each character pair. The length of the string is &lt;code&gt;N&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Looking up values in our &lt;code&gt;roman_map&lt;/code&gt; (a dictionary) takes &lt;code&gt;O(1)&lt;/code&gt; (constant time) on average.&lt;/li&gt;
&lt;li&gt;  Therefore, the total time complexity is directly proportional to the length of the input string.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We use a dictionary (&lt;code&gt;roman_map&lt;/code&gt;) to store the symbol-to-value mappings. This dictionary has a fixed size (7 entries), regardless of how long the input Roman numeral string &lt;code&gt;s&lt;/code&gt; is.&lt;/li&gt;
&lt;li&gt;  No other data structures are used that grow with the input size.&lt;/li&gt;
&lt;li&gt;  Thus, the auxiliary space used is constant.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Lookahead Pattern:&lt;/strong&gt; This problem is a classic example of when to use a "lookahead" pattern in string processing. By considering the &lt;em&gt;next&lt;/em&gt; element, you can make informed decisions about the &lt;em&gt;current&lt;/em&gt; element.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hash Maps/Dictionaries are Your Friends:&lt;/strong&gt; For quick lookups of values associated with specific keys (like Roman symbols to their integers), dictionaries are incredibly efficient and make your code clean.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Edge Cases Matter:&lt;/strong&gt; Always consider the beginning, middle, and end of your input. Here, the very last character needed special handling because our &lt;code&gt;zip&lt;/code&gt; iteration didn't include a "next" for it.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;That's it! You've successfully converted Roman numerals to integers using a clever approach. Keep practicing, and you'll be tackling even more complex problems in no time!&lt;/p&gt;




&lt;p&gt;Authored by: p1Hzd8mRM8&lt;br&gt;&lt;br&gt;
Published: 2026-05-21 17:07:27&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 12. Integer to Roman</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Thu, 21 May 2026 11:36:00 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-12-integer-to-roman-1eco</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-12-integer-to-roman-1eco</guid>
      <description>&lt;h1&gt;
  
  
  Unraveling the Mystery of Roman Numerals: A LeetCode Journey (Problem 12. Integer to Roman)
&lt;/h1&gt;

&lt;p&gt;Hey LeetCoders and aspiring developers! 👋 Today, we're taking a trip back in time to ancient Rome... well, almost! We're tackling LeetCode problem 12: "Integer to Roman." This problem asks us to convert a standard integer into its Roman numeral representation. It sounds simple, but Roman numerals have some quirky rules that make this a fun challenge. Let's dive in!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧐 Problem Explanation: What are Roman Numerals Anyway?
&lt;/h2&gt;

&lt;p&gt;Roman numerals use a system of seven symbols, each representing a specific value:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;I&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;V&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The general idea is to build numbers by adding these symbols. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;II&lt;/code&gt; = 1 + 1 = 2&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;VI&lt;/code&gt; = 5 + 1 = 6&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;LX&lt;/code&gt; = 50 + 10 = 60&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;MCC&lt;/code&gt; = 1000 + 100 + 100 = 1200&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's where it gets interesting – there are special "subtractive forms" for numbers that would otherwise require four repeated symbols or just sound clunky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Subtractive Rule:&lt;/strong&gt; If a smaller value symbol appears &lt;em&gt;before&lt;/em&gt; a larger value symbol, it means subtraction.

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;IV&lt;/code&gt; = 5 - 1 = 4 (instead of &lt;code&gt;IIII&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;IX&lt;/code&gt; = 10 - 1 = 9 (instead of &lt;code&gt;VIIII&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XL&lt;/code&gt; = 50 - 10 = 40&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;XC&lt;/code&gt; = 100 - 10 = 90&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CD&lt;/code&gt; = 500 - 100 = 400&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CM&lt;/code&gt; = 1000 - 100 = 900&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Crucially, the problem states that Roman numerals are formed by converting decimal place values from highest to lowest. This means when converting &lt;code&gt;3749&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You first convert &lt;code&gt;3000&lt;/code&gt; (MMM)&lt;/li&gt;
&lt;li&gt;  Then &lt;code&gt;700&lt;/code&gt; (DCC)&lt;/li&gt;
&lt;li&gt;  Then &lt;code&gt;40&lt;/code&gt; (XL)&lt;/li&gt;
&lt;li&gt;  Then &lt;code&gt;9&lt;/code&gt; (IX)&lt;/li&gt;
&lt;li&gt;  Combining them gives &lt;code&gt;MMMDCCXLIX&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can't do things like &lt;code&gt;IL&lt;/code&gt; for 49, because &lt;code&gt;I&lt;/code&gt; is not a decimal place lower than &lt;code&gt;L&lt;/code&gt; (which is in the tens place, &lt;code&gt;I&lt;/code&gt; is in the ones place). &lt;code&gt;49&lt;/code&gt; is &lt;code&gt;40&lt;/code&gt; (&lt;code&gt;XL&lt;/code&gt;) + &lt;code&gt;9&lt;/code&gt; (&lt;code&gt;IX&lt;/code&gt;). This "decimal place" rule is important for understanding the valid subtractive forms.&lt;/p&gt;

&lt;p&gt;Our task is to take an integer &lt;code&gt;num&lt;/code&gt; (between 1 and 3999) and return its Roman numeral string representation.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Intuition: The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;When I first look at this, my brain immediately thinks, "Okay, I need to figure out which Roman symbols make up the number." But with the additive and &lt;em&gt;especially&lt;/em&gt; the subtractive rules, a simple &lt;code&gt;if num &amp;gt;= value: add symbol&lt;/code&gt; loop might get complicated fast.&lt;/p&gt;

&lt;p&gt;The key insight comes from the combination of the specific rules and the examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Fixed Symbols &amp;amp; Values:&lt;/strong&gt; We have a known set of symbol-value pairs.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Greedy Approach:&lt;/strong&gt; We want to build the Roman numeral from left to right, which means processing the largest possible values first.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Subtractive Forms are Special:&lt;/strong&gt; &lt;code&gt;CM&lt;/code&gt; (900) is &lt;em&gt;one unit&lt;/em&gt; in the Roman system, not &lt;code&gt;D&lt;/code&gt; then &lt;code&gt;CCCC&lt;/code&gt;. Same for &lt;code&gt;CD&lt;/code&gt;, &lt;code&gt;XC&lt;/code&gt;, &lt;code&gt;XL&lt;/code&gt;, &lt;code&gt;IX&lt;/code&gt;, &lt;code&gt;IV&lt;/code&gt;. These special forms are essentially "preferred" over their additive counterparts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This leads to the "aha!" moment: If we create a list of &lt;em&gt;all valid Roman numeral values&lt;/em&gt;, including the subtractive forms, and sort them from largest to smallest, we can simply go through this list and greedily subtract the largest possible value from our input number until it becomes zero.&lt;/p&gt;

&lt;p&gt;For example, if &lt;code&gt;num = 900&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If we only considered &lt;code&gt;M=1000, D=500, C=100&lt;/code&gt;, we might try to use &lt;code&gt;D&lt;/code&gt; (500), leaving &lt;code&gt;400&lt;/code&gt;. Then try &lt;code&gt;C&lt;/code&gt; four times. This would be incorrect (&lt;code&gt;DCCCC&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  But if our list explicitly contains &lt;code&gt;(900, 'CM')&lt;/code&gt;, then &lt;code&gt;900&lt;/code&gt; would be matched directly, giving us &lt;code&gt;CM&lt;/code&gt; and the correct result.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✍️ Approach: Step-by-Step Greedy Conversion
&lt;/h2&gt;

&lt;p&gt;Based on our intuition, here's the plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a lookup table:&lt;/strong&gt; We'll define a list of tuples, where each tuple contains &lt;code&gt;(integer_value, roman_symbol_string)&lt;/code&gt;. This list is critical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It must include all standard symbols (&lt;code&gt;M&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;X&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;, &lt;code&gt;I&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  It &lt;em&gt;must&lt;/em&gt; also include the special subtractive forms (&lt;code&gt;CM&lt;/code&gt;, &lt;code&gt;CD&lt;/code&gt;, &lt;code&gt;XC&lt;/code&gt;, &lt;code&gt;XL&lt;/code&gt;, &lt;code&gt;IX&lt;/code&gt;, &lt;code&gt;IV&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Crucially, this list must be sorted in descending order of the integer values.&lt;/strong&gt; This ensures our greedy approach always picks the largest possible Roman numeral component first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our list will look something like this:&lt;br&gt;
&lt;code&gt;[(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initialize result:&lt;/strong&gt; Start with an empty list or string to build our Roman numeral. A list is generally more efficient for appending in Python, then we'll join it at the end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterate and subtract:&lt;/strong&gt; Loop through our &lt;code&gt;value_symbols&lt;/code&gt; list (which is sorted largest to smallest):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For each &lt;code&gt;(value, symbol)&lt;/code&gt; pair:

&lt;ul&gt;
&lt;li&gt;  Check how many times this &lt;code&gt;value&lt;/code&gt; can fit into our current &lt;code&gt;num&lt;/code&gt;. Let's call this &lt;code&gt;count&lt;/code&gt;. &lt;code&gt;count = num // value&lt;/code&gt; (integer division).&lt;/li&gt;
&lt;li&gt;  Append the &lt;code&gt;symbol&lt;/code&gt; repeated &lt;code&gt;count&lt;/code&gt; times to our result list. For example, if &lt;code&gt;num&lt;/code&gt; is 3000 and &lt;code&gt;value&lt;/code&gt; is 1000, &lt;code&gt;count&lt;/code&gt; will be 3, and we'll append "MMM".&lt;/li&gt;
&lt;li&gt;  Update &lt;code&gt;num&lt;/code&gt; by subtracting &lt;code&gt;count * value&lt;/code&gt; from it. This consumes the portion of the number we just converted.&lt;/li&gt;
&lt;li&gt;  We can add an early &lt;code&gt;break&lt;/code&gt; if &lt;code&gt;num&lt;/code&gt; becomes 0, as there's nothing left to convert.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Join and return:&lt;/strong&gt; Once the loop finishes, all parts of &lt;code&gt;num&lt;/code&gt; will have been converted. Join the elements in our result list into a single string and return it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's trace &lt;code&gt;num = 1994&lt;/code&gt; with this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;res = []&lt;/code&gt;, &lt;code&gt;num = 1994&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;value_symbols&lt;/code&gt; list: &lt;code&gt;[(1000, 'M'), (900, 'CM'), ..., (1, 'I')]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;value&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;symbol&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;num&lt;/code&gt; (start)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;count = num // value&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;res.append(symbol * count)&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;num -= count * value&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;num&lt;/code&gt; (end)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;'M'&lt;/td&gt;
&lt;td&gt;1994&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;res = ['M']&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1994 - 1000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;994&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;'CM'&lt;/td&gt;
&lt;td&gt;994&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;res = ['M', 'CM']&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;994 - 900&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;'D'&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;'CD'&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;'C'&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;'XC'&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;res = ['M', 'CM', 'XC']&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;94 - 90&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;'L'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;'XL'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;'X'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;'IX'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;'V'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;'IV'&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;res = ['M', 'CM', 'XC', 'IV']&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4 - 4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;'I'&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;(break loop)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;code&gt;''.join(res)&lt;/code&gt; gives us &lt;code&gt;"MCMXCIV"&lt;/code&gt;, which is the correct answer! This greedy approach, combined with a carefully constructed and ordered lookup table, handles all the Roman numeral rules elegantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;intToRoman&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Define the Roman numeral values and their corresponding symbols.
&lt;/span&gt;        &lt;span class="c1"&gt;# This list is crucial: it must be sorted in descending order of values,
&lt;/span&gt;        &lt;span class="c1"&gt;# and include the special subtractive forms (like 900 for CM)
&lt;/span&gt;        &lt;span class="c1"&gt;# BEFORE their additive components (like 500 for D and 100 for C).
&lt;/span&gt;        &lt;span class="n"&gt;value_symbols&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;M&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CM&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;D&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;XC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;L&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;XL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;IX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;V&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;IV&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Initialize an empty list to store the Roman numeral characters.
&lt;/span&gt;        &lt;span class="c1"&gt;# Appending to a list and then joining is generally more efficient
&lt;/span&gt;        &lt;span class="c1"&gt;# than repeated string concatenation in Python.
&lt;/span&gt;        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

        &lt;span class="c1"&gt;# Iterate through our defined value-symbol pairs.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;value_symbols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# If num has become 0, we've converted the entire number,
&lt;/span&gt;            &lt;span class="c1"&gt;# so we can break early.
&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;

            &lt;span class="c1"&gt;# Calculate how many times the current 'value' fits into 'num'.
&lt;/span&gt;            &lt;span class="c1"&gt;# E.g., if num = 3000 and value = 1000, count = 3.
&lt;/span&gt;            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&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;value&lt;/span&gt;

            &lt;span class="c1"&gt;# Append the 'symbol' repeated 'count' times to our result list.
&lt;/span&gt;            &lt;span class="c1"&gt;# E.g., if count = 3 and symbol = 'M', it appends 'MMM'.
&lt;/span&gt;            &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Subtract the converted portion from num.
&lt;/span&gt;            &lt;span class="c1"&gt;# E.g., num = 3000 - (3 * 1000) = 0.
&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;count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

        &lt;span class="c1"&gt;# Join all the symbols in the list to form the final Roman numeral string.
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⏱️ Time &amp;amp; Space Complexity Analysis
&lt;/h2&gt;

&lt;p&gt;Let's break down how efficient our solution is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;value_symbols&lt;/code&gt; list has a fixed size (13 elements).&lt;/li&gt;
&lt;li&gt;  We iterate through this list exactly once.&lt;/li&gt;
&lt;li&gt;  Inside the loop, operations like integer division (&lt;code&gt;//&lt;/code&gt;), multiplication (&lt;code&gt;*&lt;/code&gt;), list &lt;code&gt;append()&lt;/code&gt;, and subtraction (&lt;code&gt;-&lt;/code&gt;) take constant time. The string multiplication &lt;code&gt;symbol * count&lt;/code&gt; and &lt;code&gt;append&lt;/code&gt; are also bounded because the maximum &lt;code&gt;count&lt;/code&gt; is small (at most 3 for 'I', 'X', 'C', 'M') and the Roman numeral string's total length for &lt;code&gt;num &amp;lt;= 3999&lt;/code&gt; is very short (e.g., "MMMCMXCIX" for 3999 has 7 characters).&lt;/li&gt;
&lt;li&gt;  Since the number of iterations and the work done in each iteration are bounded by a constant (independent of the input &lt;code&gt;num&lt;/code&gt;'s magnitude, within the given constraints), the overall time complexity is constant.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;value_symbols&lt;/code&gt; list is a fixed-size data structure (13 tuples), so it takes constant space.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;res&lt;/code&gt; list stores the characters of the resulting Roman numeral string. The maximum length of a Roman numeral for an integer up to 3999 is also very small (e.g., "MMMCMXCIX" has 7 characters).&lt;/li&gt;
&lt;li&gt;  Therefore, the space used is bounded by a constant, leading to O(1) space complexity.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This solution is incredibly efficient because it leverages the fixed and relatively small nature of the Roman numeral system's rules and symbols.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Greedy Approach Power:&lt;/strong&gt; This problem is a classic example where a greedy approach shines. By always taking the largest possible valid Roman numeral component first, and ensuring your lookup table accounts for special cases (like subtractive forms) in the correct order, you can simplify complex rules.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lookup Tables are Your Friend:&lt;/strong&gt; When dealing with predefined mappings or rules, a well-structured lookup table (like our &lt;code&gt;value_symbols&lt;/code&gt; list) can make your code much cleaner and easier to reason about than a series of nested &lt;code&gt;if/else&lt;/code&gt; statements.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Order Matters!&lt;/strong&gt; For greedy algorithms, the order of elements in your lookup table is paramount. Always ensure the largest values (including special combinations) come first.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Python String Efficiency:&lt;/strong&gt; Appending to a list and then using &lt;code&gt;''.join()&lt;/code&gt; is generally more efficient for building strings than repeated string concatenation (&lt;code&gt;+=&lt;/code&gt;) in Python, especially for potentially longer strings (though in this specific problem, the string length is so small that the difference would be negligible).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;And there you have it! Converting integers to Roman numerals might seem tricky at first, but with a solid understanding of the rules and a well-designed greedy approach, it becomes quite straightforward.&lt;/p&gt;

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




&lt;p&gt;&lt;em&gt;Author Account: p1Hzd8mRM8&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Publishing Time: 2026-05-21 17:05:20&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 10. Regular Expression Matching</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Thu, 21 May 2026 11:22:46 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-10-regular-expression-matching-7hp</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-10-regular-expression-matching-7hp</guid>
      <description>&lt;h1&gt;
  
  
  Mastering Regular Expressions: A Deep Dive into LeetCode 10 with Dynamic Programming
&lt;/h1&gt;

&lt;p&gt;Hey there, fellow coders! 👋 Are you ready to tackle one of LeetCode's classic challenges that might seem daunting at first glance but becomes quite elegant with the right approach? Today, we're diving into &lt;strong&gt;Problem 10: Regular Expression Matching&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This problem is a fantastic way to sharpen your dynamic programming (DP) skills and gain a deeper understanding of how regular expressions actually work under the hood. Don't worry if regex feels like magic – we're going to demystify it together!&lt;/p&gt;




&lt;h2&gt;
  
  
  The Puzzle: Regular Expression Matching
&lt;/h2&gt;

&lt;p&gt;We're given two strings: an &lt;code&gt;input string s&lt;/code&gt; and a &lt;code&gt;pattern p&lt;/code&gt;. Our goal is to determine if the &lt;code&gt;pattern p&lt;/code&gt; completely matches the &lt;code&gt;input string s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The twist? The &lt;code&gt;pattern p&lt;/code&gt; isn't just plain text. It can contain two special characters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;'.'&lt;/code&gt;: This dot matches &lt;strong&gt;any single character&lt;/strong&gt;. Think of it as a wildcard for one character.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;'*'&lt;/code&gt;: This asterisk matches &lt;strong&gt;zero or more&lt;/strong&gt; of the &lt;em&gt;preceding element&lt;/em&gt;. This is where things get interesting!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important Note:&lt;/strong&gt; The match must cover the &lt;em&gt;entire&lt;/em&gt; input string &lt;code&gt;s&lt;/code&gt;, not just a part of it.&lt;/p&gt;

&lt;p&gt;Let's look at a few examples to solidify our understanding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Basic Mismatch&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "aa"&lt;/code&gt;, &lt;code&gt;p = "a"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; The pattern "a" only matches the first 'a' of "aa". It doesn't cover the entire string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 2: The Power of &lt;code&gt;*&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "aa"&lt;/code&gt;, &lt;code&gt;p = "a*"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; &lt;code&gt;*&lt;/code&gt; means "zero or more of the preceding element," which is 'a'. By repeating 'a' once, the pattern becomes "aa", matching the input. If &lt;code&gt;s&lt;/code&gt; was "a", it would also match (zero repetitions). If &lt;code&gt;s&lt;/code&gt; was "aaa", it would match (two repetitions).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 3: &lt;code&gt;.*&lt;/code&gt; - The Ultimate Wildcard Combo&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "ab"&lt;/code&gt;, &lt;code&gt;p = ".*"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; &lt;code&gt;.&lt;/code&gt; matches any single character. &lt;code&gt;*&lt;/code&gt; means "zero or more" of whatever precedes it. So, &lt;code&gt;.*&lt;/code&gt; means "zero or more of any character." It can match "ab", "a", "", "xyz", anything!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The "Aha!" Moment: Intuition
&lt;/h2&gt;

&lt;p&gt;When you see problems involving matching parts of strings, especially with wildcards or options like "zero or more," your mind should start thinking about &lt;strong&gt;Dynamic Programming (DP)&lt;/strong&gt;. Why DP? Because the decision at any point (does &lt;code&gt;s[i]&lt;/code&gt; match &lt;code&gt;p[j]&lt;/code&gt;) often depends on the results of smaller subproblems.&lt;/p&gt;

&lt;p&gt;Imagine trying to match &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;p[j]&lt;/code&gt; is a regular character or &lt;code&gt;.&lt;/code&gt; you just check if &lt;code&gt;s[i]&lt;/code&gt; matches &lt;code&gt;p[j]&lt;/code&gt; and then move on to matching the rest of &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  But what if &lt;code&gt;p[j]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;? This is the tricky part. &lt;code&gt;*&lt;/code&gt; gives us options:

&lt;ol&gt;
&lt;li&gt; It could match &lt;strong&gt;zero&lt;/strong&gt; occurrences of the character before it.&lt;/li&gt;
&lt;li&gt; It could match &lt;strong&gt;one or more&lt;/strong&gt; occurrences of the character before it.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These multiple choices, and the fact that we can build up a solution from smaller matches, strongly hints at DP!&lt;/p&gt;




&lt;h2&gt;
  
  
  Our Strategy: Dynamic Programming Grid
&lt;/h2&gt;

&lt;p&gt;We'll use a 2D boolean array, let's call it &lt;code&gt;dp&lt;/code&gt;, where &lt;code&gt;dp[i][j]&lt;/code&gt; will be &lt;code&gt;True&lt;/code&gt; if the first &lt;code&gt;i&lt;/code&gt; characters of &lt;code&gt;s&lt;/code&gt; (i.e., &lt;code&gt;s[0...i-1]&lt;/code&gt;) match the first &lt;code&gt;j&lt;/code&gt; characters of &lt;code&gt;p&lt;/code&gt; (i.e., &lt;code&gt;p[0...j-1]&lt;/code&gt;). Otherwise, it will be &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let &lt;code&gt;m&lt;/code&gt; be the length of &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt; be the length of &lt;code&gt;p&lt;/code&gt;. Our &lt;code&gt;dp&lt;/code&gt; table will be &lt;code&gt;(m+1) x (n+1)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize the DP Table
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;dp[0][0] = True&lt;/code&gt;: An empty string (&lt;code&gt;s&lt;/code&gt; with 0 characters) always matches an empty pattern (&lt;code&gt;p&lt;/code&gt; with 0 characters). This is our base case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First Row (&lt;code&gt;dp[0][j]&lt;/code&gt; for &lt;code&gt;j &amp;gt; 0&lt;/code&gt;):&lt;/strong&gt; This represents matching an empty string &lt;code&gt;s&lt;/code&gt; with a non-empty pattern &lt;code&gt;p&lt;/code&gt;.&lt;br&gt;
An empty string can only be matched by a pattern that allows zero characters. This typically happens with &lt;code&gt;*&lt;/code&gt;.&lt;br&gt;
If &lt;code&gt;p[j-1]&lt;/code&gt; is &lt;code&gt;'*'&lt;/code&gt;, then it can match zero of the preceding element (&lt;code&gt;p[j-2]&lt;/code&gt;). In this scenario, &lt;code&gt;dp[0][j]&lt;/code&gt; would be &lt;code&gt;True&lt;/code&gt; if &lt;code&gt;dp[0][j-2]&lt;/code&gt; was &lt;code&gt;True&lt;/code&gt;. All other &lt;code&gt;dp[0][j]&lt;/code&gt; would be &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Fill the DP Table
&lt;/h3&gt;

&lt;p&gt;We'll iterate through &lt;code&gt;s&lt;/code&gt; (from &lt;code&gt;i = 1&lt;/code&gt; to &lt;code&gt;m&lt;/code&gt;) and &lt;code&gt;p&lt;/code&gt; (from &lt;code&gt;j = 1&lt;/code&gt; to &lt;code&gt;n&lt;/code&gt;) to fill the table. For each &lt;code&gt;dp[i][j]&lt;/code&gt;, we consider two main scenarios for the current character &lt;code&gt;p[j-1]&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: &lt;code&gt;p[j-1]&lt;/code&gt; is NOT &lt;code&gt;'*'&lt;/code&gt; (i.e., it's a regular character or &lt;code&gt;'.'&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;p[j-1]&lt;/code&gt; matches &lt;code&gt;s[i-1]&lt;/code&gt; (meaning &lt;code&gt;p[j-1] == s[i-1]&lt;/code&gt; or &lt;code&gt;p[j-1] == '.'&lt;/code&gt;), then &lt;code&gt;s[0...i-1]&lt;/code&gt; matches &lt;code&gt;p[0...j-1]&lt;/code&gt; &lt;strong&gt;only if&lt;/strong&gt; &lt;code&gt;s[0...i-2]&lt;/code&gt; matched &lt;code&gt;p[0...j-2]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  So, &lt;code&gt;dp[i][j] = dp[i-1][j-1]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Otherwise (if &lt;code&gt;p[j-1]&lt;/code&gt; doesn't match &lt;code&gt;s[i-1]&lt;/code&gt;), &lt;code&gt;dp[i][j] = False&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: &lt;code&gt;p[j-1]&lt;/code&gt; IS &lt;code&gt;'*'&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the trickiest part. The &lt;code&gt;*&lt;/code&gt; implies "zero or more" of the &lt;em&gt;preceding character&lt;/em&gt; (&lt;code&gt;p[j-2]&lt;/code&gt;). Let's call this preceding character &lt;code&gt;prev_char_in_pattern = p[j-2]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have two possibilities for how &lt;code&gt;*&lt;/code&gt; can be interpreted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;*&lt;/code&gt; matches zero occurrences of &lt;code&gt;prev_char_in_pattern&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In this case, &lt;code&gt;prev_char_in_pattern&lt;/code&gt; and the &lt;code&gt;*&lt;/code&gt; effectively disappear from the pattern.&lt;/li&gt;
&lt;li&gt;  So, we need to check if &lt;code&gt;s[0...i-1]&lt;/code&gt; matches &lt;code&gt;p[0...j-3]&lt;/code&gt;. This state is represented by &lt;code&gt;dp[i][j-2]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Thus, &lt;code&gt;dp[i][j] = dp[i][j-2]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;*&lt;/code&gt; matches one or more occurrences of &lt;code&gt;prev_char_in_pattern&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For &lt;code&gt;*&lt;/code&gt; to match one or more times, &lt;code&gt;prev_char_in_pattern&lt;/code&gt; &lt;em&gt;must&lt;/em&gt; match the current character &lt;code&gt;s[i-1]&lt;/code&gt;. (i.e., &lt;code&gt;prev_char_in_pattern == s[i-1]&lt;/code&gt; or &lt;code&gt;prev_char_in_pattern == '.'&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  If they match, &lt;code&gt;s[i-1]&lt;/code&gt; is consumed by one instance of &lt;code&gt;prev_char_in_pattern&lt;/code&gt;. We then need &lt;code&gt;s[0...i-2]&lt;/code&gt; to match &lt;code&gt;p[0...j-1]&lt;/code&gt; (the &lt;code&gt;prev_char_in_pattern&lt;/code&gt; followed by &lt;code&gt;*&lt;/code&gt; is still active, potentially matching more characters).&lt;/li&gt;
&lt;li&gt;  This state is represented by &lt;code&gt;dp[i-1][j]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  So, if &lt;code&gt;prev_char_in_pattern&lt;/code&gt; matches &lt;code&gt;s[i-1]&lt;/code&gt;, then &lt;code&gt;dp[i][j]&lt;/code&gt; can also be &lt;code&gt;dp[i-1][j]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Combining these:&lt;/strong&gt; &lt;code&gt;dp[i][j]&lt;/code&gt; will be &lt;code&gt;True&lt;/code&gt; if either of these conditions holds.
&lt;code&gt;dp[i][j] = dp[i][j-2]&lt;/code&gt; (zero occurrences)
If &lt;code&gt;prev_char_in_pattern&lt;/code&gt; matches &lt;code&gt;s[i-1]&lt;/code&gt; (i.e., &lt;code&gt;p[j-2] == s[i-1]&lt;/code&gt; or &lt;code&gt;p[j-2] == '.'&lt;/code&gt;):
    &lt;code&gt;dp[i][j] = dp[i][j] or dp[i-1][j]&lt;/code&gt; (one or more occurrences)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: The Result
&lt;/h3&gt;

&lt;p&gt;After filling the entire &lt;code&gt;dp&lt;/code&gt; table, the final answer will be in &lt;code&gt;dp[m][n]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's walk through an example: &lt;code&gt;s = "aab"&lt;/code&gt;, &lt;code&gt;p = "c*a*b"&lt;/code&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dp[i][j]&lt;/th&gt;
&lt;th&gt;""&lt;/th&gt;
&lt;th&gt;c&lt;/th&gt;
&lt;th&gt;*&lt;/th&gt;
&lt;th&gt;a&lt;/th&gt;
&lt;th&gt;*&lt;/th&gt;
&lt;th&gt;b&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;""&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;a&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;aa&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;aab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;dp[0][0]&lt;/code&gt; is &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;dp[0][2]&lt;/code&gt; (for &lt;code&gt;c*&lt;/code&gt;): &lt;code&gt;p[1]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;, so &lt;code&gt;dp[0][2] = dp[0][0]&lt;/code&gt; which is &lt;code&gt;T&lt;/code&gt;. (empty string matches &lt;code&gt;c*&lt;/code&gt; by &lt;code&gt;c&lt;/code&gt; repeating 0 times).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;dp[0][4]&lt;/code&gt; (for &lt;code&gt;c*a*&lt;/code&gt;): &lt;code&gt;p[3]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;, so &lt;code&gt;dp[0][4] = dp[0][2]&lt;/code&gt; which is &lt;code&gt;T&lt;/code&gt;. (empty string matches &lt;code&gt;c*a*&lt;/code&gt; by &lt;code&gt;a&lt;/code&gt; repeating 0 times).&lt;/li&gt;
&lt;li&gt;  Now, consider &lt;code&gt;dp[1][1]&lt;/code&gt; (&lt;code&gt;s="a"&lt;/code&gt;, &lt;code&gt;p="c"&lt;/code&gt;): &lt;code&gt;p[0]&lt;/code&gt; ('c') != &lt;code&gt;s[0]&lt;/code&gt; ('a'). So &lt;code&gt;F&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Consider &lt;code&gt;dp[1][4]&lt;/code&gt; (&lt;code&gt;s="a"&lt;/code&gt;, &lt;code&gt;p="c*a*"&lt;/code&gt;):

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;p[3]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;. Preceding char &lt;code&gt;p[2]&lt;/code&gt; is 'a'.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;dp[1][2]&lt;/code&gt; (zero 'a's for &lt;code&gt;a*&lt;/code&gt;) is &lt;code&gt;F&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Does &lt;code&gt;p[2]&lt;/code&gt; ('a') match &lt;code&gt;s[0]&lt;/code&gt; ('a')? Yes!&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;dp[0][4]&lt;/code&gt; (one or more 'a's) is &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  So &lt;code&gt;dp[1][4]&lt;/code&gt; becomes &lt;code&gt;F OR T = T&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Finally, &lt;code&gt;dp[3][6]&lt;/code&gt; will be &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;isMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        :type s: str
        :type p: str
        :rtype: bool
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;m&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# dp[i][j] will be True if s[0...i-1] matches p[0...j-1]
&lt;/span&gt;        &lt;span class="c1"&gt;# Dimensions: (m+1) x (n+1)
&lt;/span&gt;        &lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="bp"&gt;False&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="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="c1"&gt;# Base case: Empty string matches empty pattern
&lt;/span&gt;        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="c1"&gt;# Initialize the first row (s is empty)
&lt;/span&gt;        &lt;span class="c1"&gt;# An empty string 's' can only match patterns like "a*", "a*b*", etc.
&lt;/span&gt;        &lt;span class="c1"&gt;# This means the pattern must end with '*' and its preceding element can be skipped.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# If p[j-1] is '*', it means zero occurrences of p[j-2].
&lt;/span&gt;                &lt;span class="c1"&gt;# So, dp[0][j] depends on whether p[0...j-3] matched an empty string.
&lt;/span&gt;                &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Fill the DP table for all other cells
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="c1"&gt;# Scenario 1: Current pattern character is a regular character or '.'
&lt;/span&gt;                &lt;span class="c1"&gt;# (p[j-1] is not '*')
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# If current characters match, depend on the match of preceding substrings
&lt;/span&gt;                    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                &lt;span class="c1"&gt;# Scenario 2: Current pattern character is '*'
&lt;/span&gt;                &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Case A: '*' matches zero occurrences of the preceding element (p[j-2])
&lt;/span&gt;                    &lt;span class="c1"&gt;# We effectively ignore p[j-2] and p[j-1] (the '*')
&lt;/span&gt;                    &lt;span class="c1"&gt;# So, s[0...i-1] must match p[0...j-3]
&lt;/span&gt;                    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                    &lt;span class="c1"&gt;# Case B: '*' matches one or more occurrences of the preceding element (p[j-2])
&lt;/span&gt;                    &lt;span class="c1"&gt;# This is only possible if the preceding character (p[j-2]) matches s[i-1]
&lt;/span&gt;                    &lt;span class="c1"&gt;# (p[j-2] == s[i-1] or p[j-2] == '.')
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="c1"&gt;# If they match, '*' consumes s[i-1], and we check if s[0...i-2] matches p[0...j-1]
&lt;/span&gt;                        &lt;span class="c1"&gt;# (where p[j-1] is still '*', allowing it to match further characters)
&lt;/span&gt;                        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&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;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Time and Space Complexity Analysis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt; &lt;code&gt;O(m * n)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We are filling an &lt;code&gt;m x n&lt;/code&gt; DP table. Each cell calculation takes constant time (a few comparisons and assignments). Therefore, the total time complexity is proportional to the product of the lengths of the string &lt;code&gt;s&lt;/code&gt; and pattern &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt; &lt;code&gt;O(m * n)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We use a 2D &lt;code&gt;dp&lt;/code&gt; array of size &lt;code&gt;(m+1) x (n+1)&lt;/code&gt; to store our intermediate results. This contributes &lt;code&gt;O(m * n)&lt;/code&gt; to the space complexity.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Given the constraints &lt;code&gt;1 &amp;lt;= s.length &amp;lt;= 20&lt;/code&gt; and &lt;code&gt;1 &amp;lt;= p.length &amp;lt;= 20&lt;/code&gt;, an &lt;code&gt;O(m*n)&lt;/code&gt; solution is perfectly efficient for this problem. &lt;code&gt;20 * 20 = 400&lt;/code&gt; operations per test case is lightning fast!&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Dynamic Programming for String Matching:&lt;/strong&gt; Problems involving matching substrings, especially with wildcards or varying length matches, are prime candidates for DP.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Defining DP State:&lt;/strong&gt; Clearly defining &lt;code&gt;dp[i][j]&lt;/code&gt; as the match for prefixes &lt;code&gt;s[0...i-1]&lt;/code&gt; and &lt;code&gt;p[0...j-1]&lt;/code&gt; is crucial.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Handling Special Characters (&lt;code&gt;.&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;.&lt;/code&gt; is straightforward: it matches any single character.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;*&lt;/code&gt; requires careful consideration: it has two main interpretations ("zero occurrences" OR "one or more occurrences") that lead to combining results from different DP states.

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zero occurrences&lt;/strong&gt;: The &lt;code&gt;*&lt;/code&gt; and its preceding character are skipped (&lt;code&gt;dp[i][j-2]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;One or more occurrences&lt;/strong&gt;: The &lt;code&gt;*&lt;/code&gt; matches the current character &lt;code&gt;s[i-1]&lt;/code&gt; (if the preceding char allows it), and the &lt;code&gt;*&lt;/code&gt; pattern remains active (&lt;code&gt;dp[i-1][j]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Base Cases:&lt;/strong&gt; Correctly initializing &lt;code&gt;dp[0][0]&lt;/code&gt; and the first row (&lt;code&gt;dp[0][j]&lt;/code&gt;) for an empty string &lt;code&gt;s&lt;/code&gt; is vital for the DP to propagate correctly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This problem is a fantastic way to stretch your DP muscles and see how complex string operations can be broken down into manageable subproblems. Keep practicing, and you'll master these patterns in no time!&lt;/p&gt;




&lt;p&gt;Published by p1Hzd8mRM8 on 2026-05-21 16:52:13&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 10. Regular Expression Matching</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Thu, 21 May 2026 09:05:53 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-10-regular-expression-matching-3e3d</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-10-regular-expression-matching-3e3d</guid>
      <description>&lt;h1&gt;
  
  
  Cracking the Regex Code: LeetCode 10 - Regular Expression Matching (Beginner-Friendly DP!)
&lt;/h1&gt;

&lt;p&gt;Hey fellow coders! 👋&lt;/p&gt;

&lt;p&gt;Today, we're diving into a classic LeetCode problem that might seem daunting at first glance but becomes incredibly elegant with the right approach: &lt;strong&gt;10. Regular Expression Matching&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you've ever used regular expressions (regex) in your programming, you know how powerful they are. This problem asks us to implement a simplified version of that power from scratch! Don't worry, we'll break it down step by step.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Regular Expression Matching 🤯
&lt;/h2&gt;

&lt;p&gt;We're given two strings: an &lt;code&gt;input string (s)&lt;/code&gt; and a &lt;code&gt;pattern (p)&lt;/code&gt;. Our mission? Determine if the pattern &lt;code&gt;p&lt;/code&gt; entirely matches the input string &lt;code&gt;s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tricky part comes with two special characters in our pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;.&lt;/code&gt; (Dot)&lt;/strong&gt;: This little guy is a wildcard! It matches &lt;em&gt;any single character&lt;/em&gt;. Think of it as a Joker card in a deck.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;*&lt;/code&gt; (Asterisk)&lt;/strong&gt;: This one is a bit more complex. It matches &lt;em&gt;zero or more&lt;/em&gt; occurrences of the &lt;em&gt;preceding element&lt;/em&gt;. The "preceding element" could be a regular character (like &lt;code&gt;a&lt;/code&gt; in &lt;code&gt;a*&lt;/code&gt;) or even a dot (&lt;code&gt;.&lt;/code&gt; in &lt;code&gt;.*&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Crucial Note:&lt;/strong&gt; The match must cover the &lt;em&gt;entire&lt;/em&gt; input string &lt;code&gt;s&lt;/code&gt;, not just a part of it.&lt;/p&gt;

&lt;p&gt;Let's look at a few examples to make it super clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "aa"&lt;/code&gt;, &lt;code&gt;p = "a"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; The pattern "a" only matches the first 'a'. It doesn't cover the entire "aa".&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "aa"&lt;/code&gt;, &lt;code&gt;p = "a*"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; The &lt;code&gt;*&lt;/code&gt; means "zero or more of the preceding 'a'". If we repeat 'a' once, it becomes "aa", which matches &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s = "ab"&lt;/code&gt;, &lt;code&gt;p = ".*"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why?&lt;/strong&gt; &lt;code&gt;.&lt;/code&gt; matches "any single character". &lt;code&gt;*&lt;/code&gt; means "zero or more of the preceding element". So, &lt;code&gt;.*&lt;/code&gt; means "zero or more of any character". This can match "ab" (specifically, it matches &lt;code&gt;a&lt;/code&gt; once, then &lt;code&gt;b&lt;/code&gt; once).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt; are pretty short (length up to 20). This is a hint that solutions with complexity like &lt;code&gt;O(len(s) * len(p))&lt;/code&gt; might pass!&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;s&lt;/code&gt; only has lowercase English letters.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;p&lt;/code&gt; has lowercase English letters, &lt;code&gt;.&lt;/code&gt;, and &lt;code&gt;*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Every &lt;code&gt;*&lt;/code&gt; in &lt;code&gt;p&lt;/code&gt; is guaranteed to have a valid preceding character (no &lt;code&gt;*abc&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Intuition: "Aha!" - It's a Matching Game! 🎮
&lt;/h2&gt;

&lt;p&gt;When you see problems asking if one string "matches" another, especially with wildcards or characters that depend on previous elements, your brain should immediately start thinking about &lt;strong&gt;Dynamic Programming (DP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why DP? Because matching involves checking if &lt;em&gt;sub-parts&lt;/em&gt; of &lt;code&gt;s&lt;/code&gt; match &lt;em&gt;sub-parts&lt;/em&gt; of &lt;code&gt;p&lt;/code&gt;. If &lt;code&gt;s[0...i]&lt;/code&gt; matches &lt;code&gt;p[0...j]&lt;/code&gt;, it likely depends on whether &lt;code&gt;s[0...i-1]&lt;/code&gt; matched &lt;code&gt;p[0...j-1]&lt;/code&gt;, or some other combination. We can build up our solution from smaller, simpler matches!&lt;/p&gt;

&lt;p&gt;Think of it like this: If you're trying to match &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt;, you look at their last characters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If they're simple characters and match, great! You just need to check if the &lt;em&gt;rest&lt;/em&gt; of &lt;code&gt;s&lt;/code&gt; matches the &lt;em&gt;rest&lt;/em&gt; of &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;p&lt;/code&gt; has a &lt;code&gt;.&lt;/code&gt; (dot), it's a free pass! It matches any character in &lt;code&gt;s&lt;/code&gt;. So again, check the rest.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;p&lt;/code&gt; has a &lt;code&gt;*&lt;/code&gt; (asterisk), this is where it gets interesting. A &lt;code&gt;*&lt;/code&gt; can represent &lt;em&gt;zero&lt;/em&gt; occurrences, &lt;em&gt;one&lt;/em&gt; occurrence, or &lt;em&gt;multiple&lt;/em&gt; occurrences. This means we have choices, and DP is excellent for exploring choices efficiently!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Approach: Building Our DP Table 🏗️
&lt;/h2&gt;

&lt;p&gt;Let's define our DP state:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dp[i][j]&lt;/code&gt; will be a boolean value, &lt;code&gt;true&lt;/code&gt; if the first &lt;code&gt;i&lt;/code&gt; characters of &lt;code&gt;s&lt;/code&gt; (i.e., &lt;code&gt;s[0...i-1]&lt;/code&gt;) match the first &lt;code&gt;j&lt;/code&gt; characters of &lt;code&gt;p&lt;/code&gt; (i.e., &lt;code&gt;p[0...j-1]&lt;/code&gt;), and &lt;code&gt;false&lt;/code&gt; otherwise.&lt;/p&gt;

&lt;p&gt;We'll create a &lt;code&gt;(m+1) x (n+1)&lt;/code&gt; 2D array (or list of lists in Python), where &lt;code&gt;m = len(s)&lt;/code&gt; and &lt;code&gt;n = len(p)&lt;/code&gt;. The extra row/column is for handling empty prefixes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Initialization (Base Cases)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;dp[0][0] = true&lt;/code&gt;: An empty string &lt;code&gt;""&lt;/code&gt; always matches an empty pattern &lt;code&gt;""&lt;/code&gt;. This is our starting point!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;dp[i][0] = false&lt;/code&gt; for &lt;code&gt;i &amp;gt; 0&lt;/code&gt;: A non-empty string &lt;code&gt;s&lt;/code&gt; can never match an empty pattern &lt;code&gt;""&lt;/code&gt;. These will remain &lt;code&gt;false&lt;/code&gt; by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;dp[0][j]&lt;/code&gt; for &lt;code&gt;j &amp;gt; 0&lt;/code&gt;: An empty string &lt;code&gt;s&lt;/code&gt; can match patterns like &lt;code&gt;"a*"&lt;/code&gt; or &lt;code&gt;"a*b*"&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;p[j-1]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;, then &lt;code&gt;dp[0][j]&lt;/code&gt; can be &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;dp[0][j-2]&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. This means the &lt;code&gt;X*&lt;/code&gt; part (where &lt;code&gt;X&lt;/code&gt; is &lt;code&gt;p[j-2]&lt;/code&gt;) is effectively skipped, matching zero occurrences of &lt;code&gt;X&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Example: For &lt;code&gt;s=""&lt;/code&gt;, &lt;code&gt;p="a*b*"&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;dp[0][0] = true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;p[1]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;. &lt;code&gt;dp[0][2]&lt;/code&gt; (for &lt;code&gt;a*&lt;/code&gt;) = &lt;code&gt;dp[0][0]&lt;/code&gt; = &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;p[3]&lt;/code&gt; is &lt;code&gt;*&lt;/code&gt;. &lt;code&gt;dp[0][4]&lt;/code&gt; (for &lt;code&gt;a*b*&lt;/code&gt;) = &lt;code&gt;dp[0][2]&lt;/code&gt; = &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Filling the DP Table (Iterative Logic)
&lt;/h3&gt;

&lt;p&gt;We'll iterate &lt;code&gt;i&lt;/code&gt; from 1 to &lt;code&gt;m&lt;/code&gt; (for &lt;code&gt;s&lt;/code&gt;) and &lt;code&gt;j&lt;/code&gt; from 1 to &lt;code&gt;n&lt;/code&gt; (for &lt;code&gt;p&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For each &lt;code&gt;dp[i][j]&lt;/code&gt;, we consider &lt;code&gt;s[i-1]&lt;/code&gt; (the current character in &lt;code&gt;s&lt;/code&gt;) and &lt;code&gt;p[j-1]&lt;/code&gt; (the current character in &lt;code&gt;p&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case 1: &lt;code&gt;p[j-1]&lt;/code&gt; is NOT &lt;code&gt;*&lt;/code&gt; (it's a regular character or &lt;code&gt;.&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;p[j-1]&lt;/code&gt; is a regular letter OR &lt;code&gt;p[j-1]&lt;/code&gt; is &lt;code&gt;.&lt;/code&gt; (the wildcard):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We need &lt;code&gt;s[i-1]&lt;/code&gt; to match &lt;code&gt;p[j-1]&lt;/code&gt; (or &lt;code&gt;p[j-1]&lt;/code&gt; is &lt;code&gt;.&lt;/code&gt; which matches anything).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If they match, then &lt;code&gt;dp[i][j]&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; if and only if the &lt;em&gt;previous parts&lt;/em&gt; also matched: &lt;code&gt;dp[i-1][j-1]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if p[j-1] == s[i-1] or p[j-1] == '.':&lt;/code&gt;&lt;br&gt;
&lt;code&gt;dp[i][j] = dp[i-1][j-1]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Case 2: &lt;code&gt;p[j-1]&lt;/code&gt; IS &lt;code&gt;*&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the most complex part, as &lt;code&gt;*&lt;/code&gt; gives us two main options for the preceding element &lt;code&gt;p[j-2]&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Option A: &lt;code&gt;*&lt;/code&gt; matches zero occurrences of &lt;code&gt;p[j-2]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;*&lt;/code&gt; matches zero occurrences, it's like &lt;code&gt;p[j-2]&lt;/code&gt; and &lt;code&gt;p[j-1]&lt;/code&gt; (&lt;code&gt;*&lt;/code&gt;) aren't even there.&lt;/li&gt;
&lt;li&gt;  So, &lt;code&gt;dp[i][j]&lt;/code&gt; would be &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;s[0...i-1]&lt;/code&gt; matches &lt;code&gt;p[0...j-3]&lt;/code&gt; (which is &lt;code&gt;dp[i][j-2]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;dp[i][j] = dp[i][j-2]&lt;/code&gt; (initial state for this cell)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Option B: &lt;code&gt;*&lt;/code&gt; matches one or more occurrences of &lt;code&gt;p[j-2]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  This is only possible if &lt;code&gt;s[i-1]&lt;/code&gt; (the current character in &lt;code&gt;s&lt;/code&gt;) actually matches &lt;code&gt;p[j-2]&lt;/code&gt; (the character &lt;em&gt;before&lt;/em&gt; &lt;code&gt;*&lt;/code&gt;). Remember &lt;code&gt;.&lt;/code&gt; also counts as a match!&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;s[i-1]&lt;/code&gt; matches &lt;code&gt;p[j-2]&lt;/code&gt; (or &lt;code&gt;p[j-2]&lt;/code&gt; is &lt;code&gt;.&lt;/code&gt;):

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;*&lt;/code&gt; matches one occurrence: &lt;code&gt;s[0...i-1]&lt;/code&gt; matches &lt;code&gt;p[0...j-1]&lt;/code&gt; if &lt;code&gt;s[0...i-2]&lt;/code&gt; matched &lt;code&gt;p[0...j-1]&lt;/code&gt; (meaning &lt;code&gt;s[i-1]&lt;/code&gt; is another occurrence of &lt;code&gt;p[j-2]&lt;/code&gt;). This is &lt;code&gt;dp[i-1][j]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  We combine this with Option A: &lt;code&gt;dp[i][j] = dp[i][j] OR dp[i-1][j]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;code&gt;if p[j-2] == s[i-1] or p[j-2] == '.':&lt;/code&gt;
&lt;code&gt;dp[i][j] = dp[i][j] or dp[i-1][j]&lt;/code&gt;
&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Putting it all together for &lt;code&gt;*&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;elif p[j-1] == '*':&lt;/code&gt;&lt;br&gt;
&lt;code&gt;dp[i][j] = dp[i][j-2]  # Option A: '*' matches zero preceding elements&lt;/code&gt;&lt;br&gt;
&lt;code&gt;if p[j-2] == s[i-1] or p[j-2] == '.':&lt;/code&gt;&lt;br&gt;
&lt;code&gt;dp[i][j] = dp[i][j] or dp[i-1][j] # Option B: '*' matches one or more&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, after filling the entire table, our answer is simply &lt;code&gt;dp[m][n]&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Code ✨
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;isMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;m&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# dp[i][j] will be true if s[0...i-1] matches p[0...j-1]
&lt;/span&gt;        &lt;span class="c1"&gt;# (m+1) rows for string s, (n+1) columns for pattern p
&lt;/span&gt;        &lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="bp"&gt;False&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="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="c1"&gt;# Base case: Empty string matches empty pattern
&lt;/span&gt;        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="c1"&gt;# Handle patterns like "a*", "a*b*", etc., matching an empty string s
&lt;/span&gt;        &lt;span class="c1"&gt;# dp[i][0] for i &amp;gt; 0 will remain False as a non-empty string cannot match an empty pattern.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# If the current pattern character is '*', it might match zero occurrences
&lt;/span&gt;            &lt;span class="c1"&gt;# of the preceding element. So, dp[0][j] depends on dp[0][j-2].
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Fill the DP table
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="c1"&gt;# Case 1: Current pattern character is a letter or '.'
&lt;/span&gt;                &lt;span class="c1"&gt;# If s[i-1] matches p[j-1] (or p[j-1] is '.'), then the match depends on
&lt;/span&gt;                &lt;span class="c1"&gt;# whether the preceding parts (s[0...i-2] and p[0...j-2]) matched.
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                &lt;span class="c1"&gt;# Case 2: Current pattern character is '*'
&lt;/span&gt;                &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Option A: '*' matches zero occurrences of the preceding element p[j-2]
&lt;/span&gt;                    &lt;span class="c1"&gt;# In this scenario, we effectively ignore p[j-2] and p[j-1] ('*').
&lt;/span&gt;                    &lt;span class="c1"&gt;# So, dp[i][j] is true if dp[i][j-2] is true.
&lt;/span&gt;                    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                    &lt;span class="c1"&gt;# Option B: '*' matches one or more occurrences of the preceding element p[j-2]
&lt;/span&gt;                    &lt;span class="c1"&gt;# This is only possible if s[i-1] matches p[j-2] (or p[j-2] is '.').
&lt;/span&gt;                    &lt;span class="c1"&gt;# If it matches, then dp[i][j] can also be true if dp[i-1][j] is true.
&lt;/span&gt;                    &lt;span class="c1"&gt;# dp[i-1][j] means s[0...i-2] already matched p[0...j-1], and now s[i-1]
&lt;/span&gt;                    &lt;span class="c1"&gt;# is another instance matching p[j-2], so the '*' consumes s[i-1].
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&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;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Time &amp;amp; Space Complexity Analysis ⏱️
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt; &lt;code&gt;O(m * n)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We are filling an &lt;code&gt;m x n&lt;/code&gt; DP table. Each cell calculation takes constant time (a few comparisons and lookups).&lt;/li&gt;
&lt;li&gt;  Given &lt;code&gt;m, n &amp;lt;= 20&lt;/code&gt;, this is &lt;code&gt;20 * 20 = 400&lt;/code&gt; operations, which is extremely fast!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt; &lt;code&gt;O(m * n)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We use a 2D &lt;code&gt;dp&lt;/code&gt; array of size &lt;code&gt;(m+1) x (n+1)&lt;/code&gt; to store our results.&lt;/li&gt;
&lt;li&gt;  Similarly, for &lt;code&gt;m, n &amp;lt;= 20&lt;/code&gt;, this is &lt;code&gt;21 * 21 = 441&lt;/code&gt; booleans, a very small memory footprint.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Takeaways ✨
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Dynamic Programming (DP) for String Matching:&lt;/strong&gt; Many string-related problems, especially those involving subproblems and choices (like &lt;code&gt;*&lt;/code&gt; representing zero or more), are excellent candidates for DP.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Careful Base Cases:&lt;/strong&gt; Correctly initializing your DP table, especially for empty strings and patterns, is crucial.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Handling Wildcards:&lt;/strong&gt; Special characters like &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt; require breaking down their behavior into distinct cases (&lt;code&gt;.&lt;/code&gt; is simple, &lt;code&gt;*&lt;/code&gt; involves "zero occurrences" vs. "one or more occurrences").&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Building from Smaller Problems:&lt;/strong&gt; The beauty of DP is seeing how &lt;code&gt;dp[i][j]&lt;/code&gt; relies on previously computed &lt;code&gt;dp&lt;/code&gt; values, allowing us to build up the complete solution efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This problem is a fantastic way to solidify your understanding of DP and string manipulation. Keep practicing, and you'll be a regex master in no time!&lt;/p&gt;




&lt;p&gt;Author Account: p1Hzd8mRM8&lt;br&gt;
Published: 2026-05-21 14:35:24&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 7. Reverse Integer</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sun, 17 May 2026 06:36:46 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-7-reverse-integer-1cl0</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-7-reverse-integer-1cl0</guid>
      <description>&lt;h1&gt;
  
  
  Unlocking LeetCode 7: Reverse Integer (A Beginner's Guide to Digital Flipping!)
&lt;/h1&gt;

&lt;p&gt;Hello Devs! Today, we're diving into a classic LeetCode problem that's perfect for honing your logical thinking and handling tricky integer constraints: &lt;strong&gt;Problem 7: Reverse Integer&lt;/strong&gt;. It sounds simple, but there's a neat catch!&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Explanation
&lt;/h2&gt;

&lt;p&gt;We're given a &lt;code&gt;signed 32-bit integer&lt;/code&gt; (that's a number that can be positive or negative, fitting within a specific range, roughly -2 billion to +2 billion). Our goal is to return this integer with its digits reversed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sounds easy, right? Here's the catch:&lt;/strong&gt; If reversing the digits causes the number to go &lt;em&gt;outside&lt;/em&gt; the valid 32-bit integer range, we must return &lt;code&gt;0&lt;/code&gt;. Also, we can't use 64-bit integers, which means we need to be careful with intermediate results if we were using a fixed-size integer language.&lt;/p&gt;

&lt;p&gt;Let's look at some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;x = 123&lt;/code&gt; becomes &lt;code&gt;321&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;x = -123&lt;/code&gt; becomes &lt;code&gt;-321&lt;/code&gt; (the sign stays!)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;x = 120&lt;/code&gt; becomes &lt;code&gt;21&lt;/code&gt; (leading zeros are dropped when reversing)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intuition
&lt;/h2&gt;

&lt;p&gt;The "aha!" moment for this problem often comes from realizing that dealing with individual digits of a number is much easier when it's &lt;em&gt;not&lt;/em&gt; a number. Think of it: how do you reverse "123"? You literally flip the order. What data type is great for flipping characters? &lt;strong&gt;Strings!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, our core idea is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Convert the integer to a string.&lt;/li&gt;
&lt;li&gt; Reverse the string.&lt;/li&gt;
&lt;li&gt; Convert it back to an integer.&lt;/li&gt;
&lt;li&gt; Perform the all-important range check.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Approach
&lt;/h2&gt;

&lt;p&gt;Let's break down the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Handle the Sign:&lt;/strong&gt; Before reversing, we need to know if the original number &lt;code&gt;x&lt;/code&gt; was negative. If &lt;code&gt;x&lt;/code&gt; is negative, we'll reverse its positive counterpart (e.g., &lt;code&gt;123&lt;/code&gt; from &lt;code&gt;-123&lt;/code&gt;) and then apply the negative sign back at the end.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Convert and Reverse:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;x&lt;/code&gt; is negative, we first take its absolute value's string representation (&lt;code&gt;str(x)[1:]&lt;/code&gt; effectively removes the &lt;code&gt;-&lt;/code&gt; sign). Then, we reverse this substring using slicing (&lt;code&gt;[::-1]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;x&lt;/code&gt; is positive, we simply convert &lt;code&gt;x&lt;/code&gt; to a string (&lt;code&gt;str(x)&lt;/code&gt;) and reverse it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Convert Back to Integer:&lt;/strong&gt; After reversing the string, we convert it back to an integer using &lt;code&gt;int()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Apply Sign (if needed):&lt;/strong&gt; If the original &lt;code&gt;x&lt;/code&gt; was negative, multiply our &lt;code&gt;res&lt;/code&gt; by &lt;code&gt;-1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Critical Overflow Check:&lt;/strong&gt; This is where many solutions fail! We need to check if our &lt;code&gt;res&lt;/code&gt; is now &lt;em&gt;outside&lt;/em&gt; the &lt;code&gt;[-2^31, 2^31 - 1]&lt;/code&gt; range.

&lt;ul&gt;
&lt;li&gt;  The maximum 32-bit signed integer is &lt;code&gt;2**31 - 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The minimum 32-bit signed integer is &lt;code&gt;-2**31&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;res&lt;/code&gt; is too large or too small, return &lt;code&gt;0&lt;/code&gt;. Otherwise, return &lt;code&gt;res&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Here's the Python implementation based on our approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Define the 32-bit integer range boundaries
&lt;/span&gt;        &lt;span class="n"&gt;MAX_INT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;MIN_INT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;

        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# For negative numbers, remove the '-' sign, reverse, then re-apply '-'
&lt;/span&gt;            &lt;span class="c1"&gt;# Example: -123 -&amp;gt; "123" -&amp;gt; "321" -&amp;gt; -321
&lt;/span&gt;            &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:][::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# For positive numbers, simply convert to string, reverse, convert back
&lt;/span&gt;            &lt;span class="c1"&gt;# Example: 123 -&amp;gt; "123" -&amp;gt; "321" -&amp;gt; 321
&lt;/span&gt;            &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# Check for 32-bit integer overflow
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_INT&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MIN_INT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Time &amp;amp; Space Complexity Analysis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Time Complexity: O(log |x|)&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  The operations involve converting the integer to a string, reversing it, and converting it back. The number of digits in &lt;code&gt;x&lt;/code&gt; is proportional to &lt;code&gt;log10(|x|)&lt;/code&gt;. All these string operations take time proportional to the number of digits.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Space Complexity: O(log |x|)&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  We create a string representation of &lt;code&gt;x&lt;/code&gt;, which uses space proportional to the number of digits in &lt;code&gt;x&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;String Magic:&lt;/strong&gt; For digit-based problems, converting integers to strings can often simplify reversal or digit manipulation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Edge Cases are Crucial:&lt;/strong&gt; Always consider negative inputs and, most importantly, the integer overflow/underflow boundaries.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Understand Data Types:&lt;/strong&gt; Be aware of the maximum and minimum values your data types can hold, especially in competitive programming.&lt;/li&gt;
&lt;/ul&gt;

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




&lt;p&gt;&lt;strong&gt;Author Account:&lt;/strong&gt; p1Hzd8mRM8&lt;br&gt;
&lt;strong&gt;Time Published:&lt;/strong&gt; 2026-05-17 12:06:31&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 5. Longest Palindromic Substring</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 18:44:09 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-5-longest-palindromic-substring-454c</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-5-longest-palindromic-substring-454c</guid>
      <description>&lt;h1&gt;
  
  
  Longest Palindromic Substring: A Core String Algorithm Explained
&lt;/h1&gt;

&lt;p&gt;Welcome to another deep dive into a classic LeetCode problem! Today, we're tackling Problem 5: Longest Palindromic Substring. This problem is a fantastic way to sharpen your string manipulation and algorithmic thinking skills.&lt;/p&gt;




&lt;h3&gt;
  
  
  Problem Explanation
&lt;/h3&gt;

&lt;p&gt;Given a string &lt;code&gt;s&lt;/code&gt;, our goal is to find and return the longest substring within &lt;code&gt;s&lt;/code&gt; that is a palindrome.&lt;/p&gt;

&lt;p&gt;What's a palindrome? It's a sequence of characters that reads the same forwards and backward (e.g., "madam", "racecar", "level").&lt;br&gt;
What's a substring? It's a contiguous sequence of characters within a string (e.g., for "apple", "app" is a substring, but "ale" is not).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's look at the examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Input: &lt;code&gt;s = "babad"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Output: &lt;code&gt;"bab"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Explanation: &lt;code&gt;"aba"&lt;/code&gt; is also a valid answer of the same length.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

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

&lt;ul&gt;
&lt;li&gt;  Input: &lt;code&gt;s = "cbbd"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Output: &lt;code&gt;"bb"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The string &lt;code&gt;s&lt;/code&gt; will contain only digits and English letters, and its length will be between 1 and 1000 characters.&lt;/p&gt;




&lt;h3&gt;
  
  
  Intuition
&lt;/h3&gt;

&lt;p&gt;The core idea behind finding palindromes is that they expand symmetrically from a center point. Think about "racecar" – the 'e' is the center, and 'c' expands to 'r'. Or "abba" – the center is between the two 'b's, and 'a' expands to 'a'.&lt;/p&gt;

&lt;p&gt;This insight simplifies our search: instead of checking every single substring for palindromic properties (which is &lt;code&gt;O(N^3)&lt;/code&gt; or &lt;code&gt;O(N^2)&lt;/code&gt; with an &lt;code&gt;O(N)&lt;/code&gt; check), we can iterate through every possible "center" and try to expand outwards.&lt;/p&gt;

&lt;p&gt;There are two types of centers we need to consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Single character center:&lt;/strong&gt; For palindromes with an odd length (e.g., "b*&lt;em&gt;a&lt;/em&gt;&lt;em&gt;b", "r&lt;/em&gt;&lt;em&gt;a&lt;/em&gt;*cecar"). Here, &lt;code&gt;s[i]&lt;/code&gt; itself is the center.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Two character center:&lt;/strong&gt; For palindromes with an even length (e.g., "bb", "a*&lt;em&gt;bb&lt;/em&gt;*a"). Here, &lt;code&gt;s[i]&lt;/code&gt; and &lt;code&gt;s[i+1]&lt;/code&gt; form the center.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Approach
&lt;/h3&gt;

&lt;p&gt;We'll use an "Expand Around Center" approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Initialize:&lt;/strong&gt; Keep track of the &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; indices of the longest palindrome found so far. Initialize them to &lt;code&gt;0, 0&lt;/code&gt; (assuming a single character is the shortest possible palindrome).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Iterate Through Centers:&lt;/strong&gt; Loop through each character in the string using an index &lt;code&gt;i&lt;/code&gt;. Each &lt;code&gt;i&lt;/code&gt; will serve as a potential center.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Expand for Odd Length Palindromes:&lt;/strong&gt; Call a helper function &lt;code&gt;expand_around_center(s, i, i)&lt;/code&gt;. This tries to expand a palindrome assuming &lt;code&gt;s[i]&lt;/code&gt; is its sole center.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Expand for Even Length Palindromes:&lt;/strong&gt; Call the helper function &lt;code&gt;expand_around_center(s, i, i + 1)&lt;/code&gt;. This tries to expand a palindrome assuming &lt;code&gt;s[i]&lt;/code&gt; and &lt;code&gt;s[i+1]&lt;/code&gt; are its two central characters.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Helper Function &lt;code&gt;expand_around_center(s, left, right)&lt;/code&gt;:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This function takes the string &lt;code&gt;s&lt;/code&gt; and two indices, &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  It expands outwards: &lt;code&gt;left&lt;/code&gt; moves to the left (&lt;code&gt;left-1&lt;/code&gt;) and &lt;code&gt;right&lt;/code&gt; moves to the right (&lt;code&gt;right+1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  This expansion continues as long as &lt;code&gt;left&lt;/code&gt; is within bounds (&lt;code&gt;&amp;gt;= 0&lt;/code&gt;), &lt;code&gt;right&lt;/code&gt; is within bounds (&lt;code&gt;&amp;lt; len(s)&lt;/code&gt;), and the characters at &lt;code&gt;s[left]&lt;/code&gt; and &lt;code&gt;s[right]&lt;/code&gt; are equal.&lt;/li&gt;
&lt;li&gt;  Once the loop terminates (either due to bounds or mismatch), the length of the palindrome found is &lt;code&gt;right - left - 1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Update Longest Palindrome:&lt;/strong&gt; After getting &lt;code&gt;len1&lt;/code&gt; (odd center) and &lt;code&gt;len2&lt;/code&gt; (even center), determine &lt;code&gt;max_len = max(len1, len2)&lt;/code&gt;. If &lt;code&gt;max_len&lt;/code&gt; is greater than the length of our current longest palindrome (&lt;code&gt;end - start + 1&lt;/code&gt;), then update &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;  To calculate the new &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; from &lt;code&gt;i&lt;/code&gt; and &lt;code&gt;max_len&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;start = i - (max_len - 1) // 2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;end = i + max_len // 2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Return Result:&lt;/strong&gt; After iterating through all possible centers, return the substring &lt;code&gt;s[start : end + 1]&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;longestPalindrome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Helper function to expand around a given center
&lt;/span&gt;        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expand_around_center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&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;left&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="c1"&gt;# When the loop finishes, left and right are one step beyond the palindrome boundaries.
&lt;/span&gt;            &lt;span class="c1"&gt;# So, the length is (right - 1) - (left + 1) + 1 = right - left - 1
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="c1"&gt;# Iterate through each character, treating it as a potential center
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="c1"&gt;# Case 1: Odd length palindrome (center is s[i])
&lt;/span&gt;            &lt;span class="n"&gt;len1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;expand_around_center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Case 2: Even length palindrome (center is s[i] and s[i+1])
&lt;/span&gt;            &lt;span class="n"&gt;len2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;expand_around_center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Get the maximum length found from these two expansions
&lt;/span&gt;            &lt;span class="n"&gt;max_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# If this palindrome is longer than our current longest
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Calculate the new start and end indices
&lt;/span&gt;                &lt;span class="c1"&gt;# For an odd length palindrome centered at i: start = i - (length-1)/2, end = i + (length-1)/2
&lt;/span&gt;                &lt;span class="c1"&gt;# For an even length palindrome centered between i and i+1: start = i - (length/2 - 1), end = i + length/2
&lt;/span&gt;                &lt;span class="c1"&gt;# The combined formula works for both:
&lt;/span&gt;                &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
                &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;max_len&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

        &lt;span class="c1"&gt;# Return the longest palindromic substring
&lt;/span&gt;        &lt;span class="k"&gt;return&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;start&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Time &amp;amp; Space Complexity Analysis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(N^2)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The main loop iterates &lt;code&gt;N&lt;/code&gt; times, where &lt;code&gt;N&lt;/code&gt; is the length of the string &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Inside the loop, &lt;code&gt;expand_around_center&lt;/code&gt; is called twice. In the worst case, &lt;code&gt;expand_around_center&lt;/code&gt; might traverse the entire string (e.g., for "aaaa...a").&lt;/li&gt;
&lt;li&gt;  Thus, each call to &lt;code&gt;expand_around_center&lt;/code&gt; takes &lt;code&gt;O(N)&lt;/code&gt; time.&lt;/li&gt;
&lt;li&gt;  Overall complexity: &lt;code&gt;N * O(N) = O(N^2)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We are only using a few variables (&lt;code&gt;start&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;len1&lt;/code&gt;, &lt;code&gt;len2&lt;/code&gt;, &lt;code&gt;max_len&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;) to store indices and lengths.&lt;/li&gt;
&lt;li&gt;  The space used does not grow with the input string size.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Palindromes and Symmetry:&lt;/strong&gt; The inherent symmetry of palindromes is key to efficient algorithms.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Expand Around Center:&lt;/strong&gt; This is a powerful technique for palindrome problems, allowing us to find palindromes by growing them from every possible middle point.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Handling Odd and Even Lengths:&lt;/strong&gt; Remember to consider both types of palindromes (odd-length with a single character center, and even-length with a two-character center).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "Expand Around Center" approach is generally simpler to implement than dynamic programming solutions for this problem, while achieving the same &lt;code&gt;O(N^2)&lt;/code&gt; time complexity.&lt;/p&gt;




&lt;p&gt;Author Account: p1Hzd8mRM8&lt;br&gt;
Time Published: 2026-05-17 00:13:54&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 4. Median of Two Sorted Arrays</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 18:42:44 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-4-median-of-two-sorted-arrays-1fc2</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-4-median-of-two-sorted-arrays-1fc2</guid>
      <description>&lt;h1&gt;
  
  
  Unlock the Median Magic: Diving into Two Sorted Arrays!
&lt;/h1&gt;

&lt;p&gt;Hey LeetCoders and aspiring developers! 👋&lt;/p&gt;

&lt;p&gt;Today, we're tackling a classic LeetCode challenge that often pops up in interviews: &lt;strong&gt;4. Median of Two Sorted Arrays&lt;/strong&gt;. Don't let the "Hard" tag intimidate you! While the optimal solution is quite advanced, we'll walk through a very intuitive, step-by-step approach that makes perfect sense for beginners. Let's conquer this one together!&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Problem Explanation: What are we actually doing?
&lt;/h2&gt;

&lt;p&gt;Imagine you have two separate lists of numbers, &lt;code&gt;nums1&lt;/code&gt; and &lt;code&gt;nums2&lt;/code&gt;, and here's the crucial part: &lt;strong&gt;both are already sorted!&lt;/strong&gt; Your mission is to find the &lt;strong&gt;median&lt;/strong&gt; of all the numbers if you were to combine these two lists into one big, sorted list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's a median?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you have an &lt;strong&gt;odd&lt;/strong&gt; number of elements in a sorted list, the median is simply the middle element. For &lt;code&gt;[1, 2, 3]&lt;/code&gt;, the median is &lt;code&gt;2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If you have an &lt;strong&gt;even&lt;/strong&gt; number of elements, the median is the average of the two middle elements. For &lt;code&gt;[1, 2, 3, 4]&lt;/code&gt;, the median is &lt;code&gt;(2 + 3) / 2 = 2.5&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem throws a curveball: it asks for an overall runtime complexity of &lt;code&gt;O(log(m+n))&lt;/code&gt;. We'll discuss this after exploring a more straightforward solution.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;nums1 = [1,3]&lt;/code&gt;, &lt;code&gt;nums2 = [2]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  If merged and sorted: &lt;code&gt;[1,2,3]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Median: &lt;code&gt;2&lt;/code&gt; (middle element)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;nums1 = [1,2]&lt;/code&gt;, &lt;code&gt;nums2 = [3,4]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  If merged and sorted: &lt;code&gt;[1,2,3,4]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Median: &lt;code&gt;(2+3)/2 = 2.5&lt;/code&gt; (average of two middle elements)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤔 Intuition: The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;The simplest way to find the median of two sorted arrays is to just... merge them! If we combine &lt;code&gt;nums1&lt;/code&gt; and &lt;code&gt;nums2&lt;/code&gt; into a single, sorted array, finding the median becomes trivial.&lt;/p&gt;

&lt;p&gt;However, actually building a &lt;em&gt;new&lt;/em&gt; merged array takes &lt;code&gt;O(m+n)&lt;/code&gt; space and time. Can we do it without fully merging? Yes! We only need to find the element(s) at the median position(s). We can simulate the merge process by using two pointers, one for each array, and pick elements one by one until we reach the median position.&lt;/p&gt;

&lt;p&gt;Think of it like this: you're trying to find the &lt;code&gt;k&lt;/code&gt;-th smallest element in the combined list. Since the arrays are sorted, you can always compare the current smallest elements from &lt;code&gt;nums1&lt;/code&gt; and &lt;code&gt;nums2&lt;/code&gt; to find the overall next smallest element. We'll just keep doing this until we've "counted" up to our median position.&lt;/p&gt;




&lt;h2&gt;
  
  
  🪜 Approach: Simulating the Merge (O(m+n) Time)
&lt;/h2&gt;

&lt;p&gt;Let's break down the step-by-step logic for our beginner-friendly O(m+n) approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Calculate Total Length &amp;amp; Median Positions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Find the total number of elements: &lt;code&gt;total_len = len(nums1) + len(nums2)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Determine if we need one median element (odd &lt;code&gt;total_len&lt;/code&gt;) or two (even &lt;code&gt;total_len&lt;/code&gt;). We'll need to iterate enough times to identify these elements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize Pointers and Median Candidates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Use two pointers, &lt;code&gt;i&lt;/code&gt; for &lt;code&gt;nums1&lt;/code&gt; and &lt;code&gt;j&lt;/code&gt; for &lt;code&gt;nums2&lt;/code&gt;, both starting at &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Introduce two variables, &lt;code&gt;m1&lt;/code&gt; and &lt;code&gt;m2&lt;/code&gt;. &lt;code&gt;m1&lt;/code&gt; will store the &lt;em&gt;current&lt;/em&gt; element identified as we iterate through the "merged" sequence. &lt;code&gt;m2&lt;/code&gt; will store the &lt;em&gt;previous&lt;/em&gt; &lt;code&gt;m1&lt;/code&gt; value. This is crucial for when we need to average two middle elements (even &lt;code&gt;total_len&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterate to the Median Position(s):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We need to find elements up to &lt;code&gt;total_len // 2 + 1&lt;/code&gt;. This ensures that for an even &lt;code&gt;total_len&lt;/code&gt;, we capture both &lt;code&gt;(total_len // 2) - 1&lt;/code&gt; and &lt;code&gt;(total_len // 2)&lt;/code&gt; elements (0-indexed).&lt;/li&gt;
&lt;li&gt;  In each iteration:

&lt;ul&gt;
&lt;li&gt;  First, &lt;code&gt;m2 = m1&lt;/code&gt;. The current &lt;code&gt;m1&lt;/code&gt; becomes the "second to last" median candidate.&lt;/li&gt;
&lt;li&gt;  Then, compare the elements &lt;code&gt;nums1[i]&lt;/code&gt; and &lt;code&gt;nums2[j]&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;nums1[i]&lt;/code&gt; is smaller (or &lt;code&gt;nums2&lt;/code&gt; is exhausted), pick &lt;code&gt;nums1[i]&lt;/code&gt;, assign it to &lt;code&gt;m1&lt;/code&gt;, and increment &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Otherwise (if &lt;code&gt;nums2[j]&lt;/code&gt; is smaller or &lt;code&gt;nums1&lt;/code&gt; is exhausted), pick &lt;code&gt;nums2[j]&lt;/code&gt;, assign it to &lt;code&gt;m1&lt;/code&gt;, and increment &lt;code&gt;j&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Calculate and Return the Median:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  After the loop finishes, &lt;code&gt;m1&lt;/code&gt; will hold the element at &lt;code&gt;total_len // 2&lt;/code&gt; (0-indexed) and &lt;code&gt;m2&lt;/code&gt; will hold the element at &lt;code&gt;(total_len // 2) - 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;total_len&lt;/code&gt; is odd, &lt;code&gt;m1&lt;/code&gt; is our median.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;total_len&lt;/code&gt; is even, the median is the average of &lt;code&gt;m1&lt;/code&gt; and &lt;code&gt;m2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach effectively "walks" through the merged sorted array without actually building it, stopping exactly when it finds the necessary median elements.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Code: The O(m+n) Merge-Like Solution (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;findMedianSortedArrays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;m&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;

        &lt;span class="c1"&gt;# m1 will store the element at the current "median" position
&lt;/span&gt;        &lt;span class="c1"&gt;# m2 will store the element at the "median-1" position (for even total_len)
&lt;/span&gt;        &lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 

        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# Pointers for nums1 and nums2
&lt;/span&gt;
        &lt;span class="c1"&gt;# Iterate (m + n) // 2 + 1 times to find the median element(s)
&lt;/span&gt;        &lt;span class="c1"&gt;# We need to iterate one more time than total_len // 2 for even arrays
&lt;/span&gt;        &lt;span class="c1"&gt;# to capture both m1 and m2 correctly.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_len&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;m2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m1&lt;/span&gt; &lt;span class="c1"&gt;# m2 takes the value m1 had in the previous iteration
&lt;/span&gt;
            &lt;span class="c1"&gt;# Logic to pick the next smallest element from either nums1 or nums2
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&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="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
                &lt;span class="n"&gt;m1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nums1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# j &amp;lt; n and (i &amp;gt;= m or nums2[j] &amp;lt;= nums1[i])
&lt;/span&gt;                &lt;span class="n"&gt;m1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nums2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="c1"&gt;# Check if the sum of n and m is odd.
&lt;/span&gt;        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m1&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;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m2&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;ans&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⏱️ Time &amp;amp; Space Complexity Analysis
&lt;/h2&gt;

&lt;p&gt;For the O(m+n) solution we just explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Time Complexity: &lt;code&gt;O(m+n)&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  We iterate through the arrays up to &lt;code&gt;(m+n)/2 + 1&lt;/code&gt; times in the worst case. This is directly proportional to the total number of elements.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Space Complexity: &lt;code&gt;O(1)&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  We only use a few extra variables (&lt;code&gt;m1&lt;/code&gt;, &lt;code&gt;m2&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;, &lt;code&gt;total_len&lt;/code&gt;). We don't create any new arrays proportional to the input size.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A Note on the &lt;code&gt;O(log(m+n))&lt;/code&gt; Requirement:&lt;/strong&gt;&lt;br&gt;
The problem statement &lt;em&gt;does&lt;/em&gt; ask for an &lt;code&gt;O(log(m+n))&lt;/code&gt; runtime complexity. This typically points to a more advanced solution involving &lt;strong&gt;binary search on partitions&lt;/strong&gt;. That approach is significantly more complex and often involves finding a "split point" in both arrays such that the elements to the left of the split form the lower half of the merged array, and elements to the right form the upper half.&lt;/p&gt;

&lt;p&gt;While our &lt;code&gt;O(m+n)&lt;/code&gt; solution is intuitive and a great starting point, mastering the &lt;code&gt;O(log(m+n))&lt;/code&gt; binary search approach is a fantastic next step once you're comfortable with this basic idea!&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Simulate, Don't Always Build:&lt;/strong&gt; For problems involving sorted arrays and finding specific elements (like the median or k-th smallest), you often don't need to physically merge them. Simulating the merge with pointers is efficient.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Median Logic:&lt;/strong&gt; Remember the difference between odd and even total lengths for calculating the median. Keeping track of two "median candidate" variables (&lt;code&gt;m1&lt;/code&gt; and &lt;code&gt;m2&lt;/code&gt;) helps simplify this.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Complexity Matters:&lt;/strong&gt; Always be aware of the optimal time complexity required for a problem. While an &lt;code&gt;O(m+n)&lt;/code&gt; solution is often a good first step, understanding the &lt;code&gt;O(log(m+n))&lt;/code&gt; binary search approach for this specific problem is key for interviews.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding, and keep practicing! You're doing great!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Author Account: p1Hzd8mRM8&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Time Published: 2026-05-17 00:12:16&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 3. Longest Substring Without Repeating Characters</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 17:38:35 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-3-longest-substring-without-repeating-characters-l9l</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-3-longest-substring-without-repeating-characters-l9l</guid>
      <description>&lt;h1&gt;
  
  
  Sliding into Success: Solving LeetCode 3 - Longest Substring Without Repeating Characters
&lt;/h1&gt;

&lt;p&gt;Hey there, aspiring competitive programmers and curious coders!&lt;/p&gt;

&lt;p&gt;Today, we're diving into a classic LeetCode problem that's a fantastic introduction to a super useful technique: the &lt;em&gt;Sliding Window&lt;/em&gt;. It's problem #3, "Longest Substring Without Repeating Characters," and it's a rite of passage for many!&lt;/p&gt;

&lt;p&gt;Don't let the name intimidate you. By the end of this post, you'll not only understand it but also appreciate the elegance of its solution.&lt;/p&gt;




&lt;h3&gt;
  
  
  Problem Explanation: What are we actually trying to find?
&lt;/h3&gt;

&lt;p&gt;The problem asks us to find the length of the longest &lt;strong&gt;substring&lt;/strong&gt; within a given string &lt;code&gt;s&lt;/code&gt; that doesn't have any repeating characters.&lt;/p&gt;

&lt;p&gt;Let's break down some keywords:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;String &lt;code&gt;s&lt;/code&gt;&lt;/strong&gt;: This is our input, like &lt;code&gt;"abcabcbb"&lt;/code&gt; or &lt;code&gt;"pwwkew"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Substring&lt;/strong&gt;: This is a &lt;em&gt;contiguous&lt;/em&gt; sequence of characters within a string. For example, in &lt;code&gt;"abc"&lt;/code&gt;, &lt;code&gt;"a"&lt;/code&gt;, &lt;code&gt;"ab"&lt;/code&gt;, &lt;code&gt;"bc"&lt;/code&gt;, &lt;code&gt;"abc"&lt;/code&gt; are substrings. &lt;code&gt;"ac"&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a substring because the characters aren't consecutive.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Without repeating characters&lt;/strong&gt;: Every character in our substring must be unique. If we see 'a', we can't have another 'a' in the same substring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let's look at the examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;s = "abcabcbb"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;"abc"&lt;/code&gt; is a substring without repeating characters (length 3).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;"bca"&lt;/code&gt; is also a substring without repeating characters (length 3).&lt;/li&gt;
&lt;li&gt;  The longest such substring has a length of &lt;strong&gt;3&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;s = "bbbbb"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;"b"&lt;/code&gt; is the longest substring without repeating characters (length 1).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;s = "pwwkew"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;"pw"&lt;/code&gt; (length 2)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;"wke"&lt;/code&gt; (length 3) - This is our winner!&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;"kew"&lt;/code&gt; (length 3) - Another winner!&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;IMPORTANT&lt;/strong&gt;: &lt;code&gt;"pwke"&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a substring, it's a subsequence. Remember, substrings must be contiguous. &lt;code&gt;"wke"&lt;/code&gt; is valid because 'w', 'k', 'e' are consecutive.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Our goal is to return just the &lt;em&gt;length&lt;/em&gt; of this longest unique-character substring.&lt;/p&gt;




&lt;h3&gt;
  
  
  Intuition: The "Aha!" Moment
&lt;/h3&gt;

&lt;p&gt;Imagine you're looking at a street. You want to find the longest stretch of unique houses (characters). You start walking, adding each new house you see to your mental list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you see a house you've already listed, you know your current unique stretch has ended &lt;em&gt;at or before&lt;/em&gt; this duplicate.&lt;/li&gt;
&lt;li&gt;  To continue, you can't just skip the duplicate. You need to "forget" houses from the &lt;em&gt;beginning&lt;/em&gt; of your current stretch until the duplicate is no longer in your list. Then, you can add the current house and keep walking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "walking" and "forgetting" sounds like a &lt;strong&gt;Sliding Window&lt;/strong&gt;! We'll have two pointers: &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;right&lt;/code&gt; expands our window, bringing new characters in.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;left&lt;/code&gt; shrinks our window when we encounter a duplicate, removing characters from the start until the duplicate is gone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At each step, we'll keep track of the maximum length our window has ever achieved.&lt;/p&gt;




&lt;h3&gt;
  
  
  Approach: Building Our Sliding Window
&lt;/h3&gt;

&lt;p&gt;We'll use two pointers, &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;, to define our current "window" (substring). We also need a way to quickly check if a character is already in our current window. A &lt;code&gt;Set&lt;/code&gt; (or &lt;code&gt;HashSet&lt;/code&gt; in some languages) is perfect for this, as it allows for O(1) average time complexity for add, remove, and check operations.&lt;/p&gt;

&lt;p&gt;Here's the step-by-step logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;left = 0&lt;/code&gt;: This pointer marks the beginning of our current unique substring.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;max_length = 0&lt;/code&gt;: This will store the maximum length we've found so far.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;char_set = set()&lt;/code&gt;: An empty set to store characters currently within our window &lt;code&gt;[left, right]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterate with &lt;code&gt;right&lt;/code&gt; pointer&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We'll use a &lt;code&gt;for&lt;/code&gt; loop, letting &lt;code&gt;right&lt;/code&gt; traverse the input string &lt;code&gt;s&lt;/code&gt; from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;len(s) - 1&lt;/code&gt;. This pointer expands our window to the right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check for Duplicates&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Inside the loop, before adding &lt;code&gt;s[right]&lt;/code&gt; to our &lt;code&gt;char_set&lt;/code&gt;, we check if &lt;code&gt;s[right]&lt;/code&gt; is &lt;em&gt;already&lt;/em&gt; in &lt;code&gt;char_set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;If &lt;code&gt;s[right]&lt;/code&gt; IS in &lt;code&gt;char_set&lt;/code&gt; (duplicate found)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  This means our current window &lt;code&gt;s[left...right-1]&lt;/code&gt; has a duplicate if &lt;code&gt;s[right]&lt;/code&gt; is added.&lt;/li&gt;
&lt;li&gt;  To resolve this, we need to shrink our window from the &lt;code&gt;left&lt;/code&gt; side.&lt;/li&gt;
&lt;li&gt;  We enter a &lt;code&gt;while&lt;/code&gt; loop:

&lt;ul&gt;
&lt;li&gt;  Remove &lt;code&gt;s[left]&lt;/code&gt; from &lt;code&gt;char_set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Increment &lt;code&gt;left&lt;/code&gt; by 1.&lt;/li&gt;
&lt;li&gt;  Repeat this until &lt;code&gt;s[right]&lt;/code&gt; is no longer in &lt;code&gt;char_set&lt;/code&gt;. This ensures our window &lt;code&gt;s[left...right-1]&lt;/code&gt; is unique &lt;em&gt;before&lt;/em&gt; we add &lt;code&gt;s[right]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;If &lt;code&gt;s[right]&lt;/code&gt; IS NOT in &lt;code&gt;char_set&lt;/code&gt; (unique character)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;  Great! We can safely add &lt;code&gt;s[right]&lt;/code&gt; to &lt;code&gt;char_set&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;max_length&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  After &lt;code&gt;s[right]&lt;/code&gt; has been added (and duplicates handled if any), our current window &lt;code&gt;s[left...right]&lt;/code&gt; is guaranteed to be unique.&lt;/li&gt;
&lt;li&gt;  The length of this current unique window is &lt;code&gt;right - left + 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Update &lt;code&gt;max_length = max(max_length, right - left + 1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Return&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  After the &lt;code&gt;right&lt;/code&gt; pointer has traversed the entire string, &lt;code&gt;max_length&lt;/code&gt; will hold the length of the longest substring without repeating characters. Return &lt;code&gt;max_length&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's walk through &lt;code&gt;s = "abcabcbb"&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;right&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;s[right]&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;char_set&lt;/code&gt; (before add)&lt;/th&gt;
&lt;th&gt;Duplicate?&lt;/th&gt;
&lt;th&gt;Actions (if duplicate)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;char_set&lt;/code&gt; (after add)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;left&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Current Length (&lt;code&gt;right - left + 1&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;max_length&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;'a'&lt;/td&gt;
&lt;td&gt;{}&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;{'a'}&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;'b'&lt;/td&gt;
&lt;td&gt;{'a'}&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;{'a', 'b'}&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;'c'&lt;/td&gt;
&lt;td&gt;{'a', 'b'}&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;{'a', 'b', 'c'}&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;'a'&lt;/td&gt;
&lt;td&gt;{'a', 'b', 'c'}&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;char_set.remove('a')&lt;/code&gt;, &lt;code&gt;left=1&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;{'b', 'c', 'a'}&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3 (&lt;code&gt;3 - 1 + 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;'b'&lt;/td&gt;
&lt;td&gt;{'b', 'c', 'a'}&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;char_set.remove('b')&lt;/code&gt;, &lt;code&gt;left=2&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;{'c', 'a', 'b'}&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3 (&lt;code&gt;4 - 2 + 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;'c'&lt;/td&gt;
&lt;td&gt;{'c', 'a', 'b'}&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;char_set.remove('c')&lt;/code&gt;, &lt;code&gt;left=3&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;{'a', 'b', 'c'}&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3 (&lt;code&gt;5 - 3 + 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;'b'&lt;/td&gt;
&lt;td&gt;{'a', 'b', 'c'}&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;char_set.remove('a')&lt;/code&gt;, &lt;code&gt;left=4&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;{'b', 'c', 'b'}&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3 (&lt;code&gt;6 - 4 + 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;char_set.remove('b')&lt;/code&gt;, &lt;code&gt;left=5&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;{'c', 'b'}&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2 (&lt;code&gt;6 - 5 + 1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Final &lt;code&gt;max_length&lt;/code&gt; is 3. This trace confirms the logic!&lt;/p&gt;




&lt;h3&gt;
  
  
  Code: Bringing it to life with Python
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lengthOfLongestSubstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# A set to keep track of characters in the current window
&lt;/span&gt;        &lt;span class="n"&gt;char_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Left pointer of the sliding window
&lt;/span&gt;        &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Variable to store the maximum length found so far
&lt;/span&gt;        &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Right pointer iterates through the string
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="c1"&gt;# If the character at 'right' is already in our set,
&lt;/span&gt;            &lt;span class="c1"&gt;# it means we have a duplicate within the current window.
&lt;/span&gt;            &lt;span class="c1"&gt;# We need to shrink the window from the 'left' until the duplicate is removed.
&lt;/span&gt;            &lt;span class="k"&gt;while&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;right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# Remove the character at 'left' from the set
&lt;/span&gt;                &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;                &lt;span class="c1"&gt;# Move the 'left' pointer one step to the right
&lt;/span&gt;
            &lt;span class="c1"&gt;# Now that the current character s[right] is guaranteed to be unique
&lt;/span&gt;            &lt;span class="c1"&gt;# in the window [left...right-1], we can add it to our set.
&lt;/span&gt;            &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

            &lt;span class="c1"&gt;# Update the maximum length found.
&lt;/span&gt;            &lt;span class="c1"&gt;# The current window length is (right - left + 1).
&lt;/span&gt;            &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Time &amp;amp; Space Complexity Analysis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(N)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Both the &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; pointers traverse the string &lt;code&gt;s&lt;/code&gt; at most once.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;right&lt;/code&gt; pointer moves &lt;code&gt;N&lt;/code&gt; times.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;left&lt;/code&gt; pointer also moves at most &lt;code&gt;N&lt;/code&gt; times across all iterations of the outer loop.&lt;/li&gt;
&lt;li&gt;  Set operations (add, remove, check &lt;code&gt;in&lt;/code&gt;) take O(1) average time.&lt;/li&gt;
&lt;li&gt;  Therefore, the total time complexity is linear, O(N), where &lt;code&gt;N&lt;/code&gt; is the length of the string &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(min(M, N))&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We use a &lt;code&gt;char_set&lt;/code&gt; to store unique characters within the window.&lt;/li&gt;
&lt;li&gt;  In the worst case, if all characters in the string are unique (e.g., "abcdefg"), the set will store &lt;code&gt;N&lt;/code&gt; characters.&lt;/li&gt;
&lt;li&gt;  However, if the character set is limited (e.g., lowercase English letters, &lt;code&gt;M=26&lt;/code&gt;), the set will store at most &lt;code&gt;M&lt;/code&gt; characters.&lt;/li&gt;
&lt;li&gt;  So, the space complexity is bounded by the smaller of the string's length &lt;code&gt;N&lt;/code&gt; and the size of the character set &lt;code&gt;M&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Sliding Window Technique&lt;/strong&gt;: This problem is a prime example of the "sliding window" pattern, which is incredibly useful for array/string problems involving a contiguous subsegment. It helps optimize solutions from O(N^2) (e.g., checking every possible substring) to O(N).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;Set&lt;/code&gt; for Uniqueness Checks&lt;/strong&gt;: Using a hash set (&lt;code&gt;set&lt;/code&gt; in Python) is crucial for efficient O(1) average-time lookups, insertions, and deletions, which allows the sliding window to perform optimally.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Two Pointers (Left and Right)&lt;/strong&gt;: The &lt;code&gt;left&lt;/code&gt; pointer helps shrink the window when a condition is violated (duplicate found), while the &lt;code&gt;right&lt;/code&gt; pointer expands it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keep practicing, and you'll master these patterns in no time! Happy coding!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Author Account: p1Hzd8mRM8&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Time Published: 2026-05-16 23:08:20&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 3. Longest Substring Without Repeating Characters</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 17:30:51 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-3-longest-substring-without-repeating-characters-2nm3</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-3-longest-substring-without-repeating-characters-2nm3</guid>
      <description>&lt;h1&gt;
  
  
  Cracking LeetCode 3: The Longest Substring Without Repeating Characters (A Sliding Window Adventure!)
&lt;/h1&gt;

&lt;p&gt;Hey Devs! 👋 Ever stumbled upon a LeetCode problem that looks simple but hides a powerful algorithmic pattern? Today, we're diving into LeetCode problem #3, "Longest Substring Without Repeating Characters." This classic problem is a fantastic introduction to a super common and efficient technique: the &lt;strong&gt;Sliding Window&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Don't worry if that sounds intimidating – we'll break it down piece by piece, like LEGOs! By the end of this post, you'll not only understand the solution but also gain a valuable tool for tackling similar string and array problems. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Unpacking "Longest Substring Without Repeating Characters"
&lt;/h2&gt;

&lt;p&gt;Imagine you're given a string, like "abcabcbb". Your mission, should you choose to accept it, is to find the longest &lt;em&gt;substring&lt;/em&gt; within it that doesn't have any character repeated.&lt;/p&gt;

&lt;p&gt;Let's clarify some terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Substring&lt;/strong&gt;: A contiguous sequence of characters within a string. "abc" is a substring of "abcabcbb", but "acb" is not.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Without Repeating Characters&lt;/strong&gt;: Every character in our chosen substring must be unique. No 'a' appearing twice, no 'b' appearing twice, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples to make it crystal clear:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Input: &lt;code&gt;s = "abcabcbb"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  "abc" is a substring without repeating characters (length 3).&lt;/li&gt;
&lt;li&gt;  "bca" is also valid (length 3).&lt;/li&gt;
&lt;li&gt;  "abcab" is NOT valid because 'a' and 'b' repeat.&lt;/li&gt;
&lt;li&gt;  The longest one we can find is "abc" (or "bca", "cab"), with a length of &lt;strong&gt;3&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Input: &lt;code&gt;s = "bbbbb"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The longest substring without repeating characters is just "b" (length &lt;strong&gt;1&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Input: &lt;code&gt;s = "pwwkew"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  "pwke" is NOT a substring; it's a &lt;em&gt;subsequence&lt;/em&gt; (characters appear in order but not necessarily contiguously).&lt;/li&gt;
&lt;li&gt;  "wke" IS a substring without repeating characters (length 3).&lt;/li&gt;
&lt;li&gt;  "pww" has repeating 'w'.&lt;/li&gt;
&lt;li&gt;  The longest is "wke" (length &lt;strong&gt;3&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The goal is to return just the &lt;em&gt;length&lt;/em&gt; of this longest unique substring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Intuition: Why a "Sliding Window"?
&lt;/h2&gt;

&lt;p&gt;If you're new to competitive programming, your first thought might be: "Let's check every possible substring!" And that's a valid starting point. You could have two loops, &lt;code&gt;i&lt;/code&gt; and &lt;code&gt;j&lt;/code&gt;, generating all substrings &lt;code&gt;s[i:j+1]&lt;/code&gt;, and for each, check if it has repeating characters. This would work, but it's pretty slow (think O(N^3) or O(N^2) depending on how you check uniqueness). Can we do better? Absolutely!&lt;/p&gt;

&lt;p&gt;The "aha!" moment comes when you realize that if you have a substring &lt;code&gt;s[left...right]&lt;/code&gt; that contains duplicate characters, you don't need to re-examine the &lt;em&gt;entire&lt;/em&gt; string from scratch. You just need to &lt;em&gt;adjust&lt;/em&gt; your current substring until it becomes valid again.&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;Sliding Window&lt;/strong&gt; technique shines! Imagine a window "sliding" over the string. This window represents our current substring.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We try to expand the window from the &lt;code&gt;right&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If we add a character that causes a duplicate, we shrink the window from the &lt;code&gt;left&lt;/code&gt; until the duplicate is gone.&lt;/li&gt;
&lt;li&gt;  At each valid step, we keep track of the maximum length our window has achieved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Approach: Two Pointers and a Set
&lt;/h2&gt;

&lt;p&gt;Let's formalize our sliding window approach using two pointers, &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;, and a &lt;code&gt;set&lt;/code&gt; to efficiently track characters within our current window.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;max_length = 0&lt;/code&gt;: This will store our answer.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;left = 0&lt;/code&gt;: This pointer marks the beginning of our current unique substring window.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;char_set = set()&lt;/code&gt;: This set will hold all characters currently inside our &lt;code&gt;s[left...right]&lt;/code&gt; window. Sets are perfect because they only store unique items and offer super fast &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt;, and &lt;code&gt;in&lt;/code&gt; (contains) operations (average O(1) time complexity).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Iterate with the &lt;code&gt;right&lt;/code&gt; pointer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We'll use a &lt;code&gt;for&lt;/code&gt; loop with &lt;code&gt;right&lt;/code&gt; iterating from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;len(s) - 1&lt;/code&gt;. This pointer expands our window to the right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check for Duplicates and Shrink the Window:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Inside the loop, before adding &lt;code&gt;s[right]&lt;/code&gt; to our &lt;code&gt;char_set&lt;/code&gt;, we need to check if &lt;code&gt;s[right]&lt;/code&gt; is &lt;em&gt;already&lt;/em&gt; in &lt;code&gt;char_set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;If &lt;code&gt;s[right]&lt;/code&gt; is ALREADY in &lt;code&gt;char_set&lt;/code&gt;&lt;/strong&gt;: This means we have a duplicate! Our current window &lt;code&gt;s[left...right-1]&lt;/code&gt; was unique, but &lt;code&gt;s[right]&lt;/code&gt; broke the rule.

&lt;ul&gt;
&lt;li&gt;  To fix this, we need to shrink the window from the &lt;code&gt;left&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  We repeatedly &lt;code&gt;remove&lt;/code&gt; &lt;code&gt;s[left]&lt;/code&gt; from &lt;code&gt;char_set&lt;/code&gt; and increment &lt;code&gt;left&lt;/code&gt; until &lt;code&gt;s[right]&lt;/code&gt; is no longer a duplicate within our window.&lt;/li&gt;
&lt;li&gt;  Think of it as kicking out characters from the left until the culprit (the first instance of the duplicate) is gone.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Expand the Window and Update Max Length:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Once &lt;code&gt;s[right]&lt;/code&gt; is guaranteed to be unique within our current (possibly shrunken) window, &lt;code&gt;add&lt;/code&gt; &lt;code&gt;s[right]&lt;/code&gt; to &lt;code&gt;char_set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Now, our current window &lt;code&gt;s[left...right]&lt;/code&gt; is valid (all unique characters). Calculate its length: &lt;code&gt;right - left + 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Update &lt;code&gt;max_length = max(max_length, right - left + 1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return &lt;code&gt;max_length&lt;/code&gt;:&lt;/strong&gt; After the &lt;code&gt;right&lt;/code&gt; pointer has traversed the entire string, &lt;code&gt;max_length&lt;/code&gt; will hold the length of the longest substring without repeating characters.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's trace &lt;code&gt;s = "abcabcbb"&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;right&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;s[right]&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;char_set&lt;/code&gt; (before &lt;code&gt;s[right]&lt;/code&gt; check)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;s[right]&lt;/code&gt; in &lt;code&gt;char_set&lt;/code&gt;?&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;char_set&lt;/code&gt; (after fix)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;left&lt;/code&gt; (after fix)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;char_set&lt;/code&gt; (after add &lt;code&gt;s[right]&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Current Window (&lt;code&gt;s[left...right]&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Current Length&lt;/th&gt;
&lt;th&gt;&lt;code&gt;max_length&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;False&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;False&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ab&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;False&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b, c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;abc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b, c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; (a repeats)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{b, c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{b, c, a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bca&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{b, c, a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; (b repeats)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c, a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c, a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cab&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c, a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; (c repeats)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b, c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;abc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a, b, c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; (b repeats)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{c, b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; (b repeats)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{b}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;code&gt;max_length&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt;! This matches the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lengthOfLongestSubstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;char_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# To store characters in the current window
&lt;/span&gt;        &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;         &lt;span class="c1"&gt;# Left pointer of the sliding window
&lt;/span&gt;        &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;   &lt;span class="c1"&gt;# Stores the maximum length found so far
&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="c1"&gt;# While the character at 'right' is already in our set (duplicate detected)
&lt;/span&gt;            &lt;span class="k"&gt;while&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;right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Remove the character at 'left' from the set
&lt;/span&gt;                &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="c1"&gt;# Move the 'left' pointer to shrink the window
&lt;/span&gt;                &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="c1"&gt;# Add the current character at 'right' to the set
&lt;/span&gt;            &lt;span class="c1"&gt;# Now, the window s[left...right] is guaranteed to have unique characters
&lt;/span&gt;            &lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

            &lt;span class="c1"&gt;# Update the maximum length found
&lt;/span&gt;            &lt;span class="n"&gt;max_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Time &amp;amp; Space Complexity Analysis
&lt;/h2&gt;

&lt;p&gt;This is where the sliding window truly shines!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(N)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;right&lt;/code&gt; pointer iterates through the string &lt;code&gt;s&lt;/code&gt; exactly once, performing &lt;code&gt;N&lt;/code&gt; steps.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;left&lt;/code&gt; pointer also iterates through the string at most once (it only moves forward).&lt;/li&gt;
&lt;li&gt;  Each character is added to the &lt;code&gt;char_set&lt;/code&gt; once and removed from the &lt;code&gt;char_set&lt;/code&gt; at most once.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;set&lt;/code&gt; operations (add, remove, check &lt;code&gt;in&lt;/code&gt;) take average O(1) time.&lt;/li&gt;
&lt;li&gt;  Therefore, the total time complexity is linear, O(N), where N is the length of the string &lt;code&gt;s&lt;/code&gt;. This is super efficient!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(min(N, M))&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;char_set&lt;/code&gt; stores characters from the current window.&lt;/li&gt;
&lt;li&gt;  In the worst case, if all characters are unique, the set could store up to &lt;code&gt;N&lt;/code&gt; characters (where N is &lt;code&gt;len(s)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  However, the maximum size of the &lt;code&gt;char_set&lt;/code&gt; is also limited by the size of the character set (e.g., 26 for lowercase English letters, 128 for ASCII, 256 for extended ASCII). Let &lt;code&gt;M&lt;/code&gt; be the size of the alphabet.&lt;/li&gt;
&lt;li&gt;  So, the space complexity is O(min(N, M)). For typical interview problems dealing with ASCII characters, this is often considered O(1) constant space because &lt;code&gt;M&lt;/code&gt; (e.g., 128 or 256) is a fixed constant regardless of the input string's length.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Sliding Window Power&lt;/strong&gt;: This problem is a perfect introduction to the sliding window pattern. Remember it for problems involving finding optimal subarrays or substrings.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Two Pointers&lt;/strong&gt;: The &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; pointers are crucial for defining and moving the window efficiently.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Hash Set (Set) for Uniqueness&lt;/strong&gt;: A &lt;code&gt;set&lt;/code&gt; is your best friend when you need to quickly check for the presence of an element and ensure uniqueness. Its O(1) average time complexity for lookups, insertions, and deletions is key to the overall efficiency.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Distinguish Substring vs. Subsequence&lt;/strong&gt;: Always pay attention to whether the problem asks for a &lt;em&gt;substring&lt;/em&gt; (contiguous) or a &lt;em&gt;subsequence&lt;/em&gt; (order preserved, not necessarily contiguous).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Congratulations! You've successfully navigated one of LeetCode's most popular problems and added the powerful Sliding Window technique to your algorithmic toolkit. Keep practicing, and these patterns will become second nature!&lt;/p&gt;




&lt;p&gt;Published by p1Hzd8mRM8 on 2026-05-16 23:00:35&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 2. Add Two Numbers</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 17:28:37 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-2-add-two-numbers-5074</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-2-add-two-numbers-5074</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Cracking LeetCode #2: Adding Two Numbers Like a Pro (with Linked Lists!) 🚀
&lt;/h1&gt;

&lt;p&gt;Hey there, future coding rockstars! 👋 Today, we're diving into a LeetCode classic that often stumps beginners but is incredibly satisfying once you "get" it. We're talking about &lt;strong&gt;LeetCode Problem #2: Add Two Numbers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This problem is a fantastic introduction to manipulating linked lists and thinking about how computers handle fundamental operations like arithmetic. Ready to conquer it? Let's go!&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem Explained: Adding Numbers, But Backwards! 🤯
&lt;/h3&gt;

&lt;p&gt;Imagine you want to add two big numbers, like 342 and 465. Normally, you'd write them down and add them from right to left (units, tens, hundreds, etc.), carrying over any extra digits.&lt;/p&gt;

&lt;p&gt;Now, imagine these numbers aren't stored as regular integers but as &lt;strong&gt;linked lists&lt;/strong&gt;. If you're new to linked lists, think of them as a chain of boxes (nodes), where each box holds a value and points to the &lt;em&gt;next&lt;/em&gt; box in the chain.&lt;/p&gt;

&lt;p&gt;The twist? The digits are stored in &lt;strong&gt;reverse order&lt;/strong&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;l1 = [2,4,3]&lt;/code&gt; actually represents the number &lt;strong&gt;342&lt;/strong&gt;. (3 -&amp;gt; 4 -&amp;gt; 2, but read from the head: 2 is units, 4 is tens, 3 is hundreds).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;l2 = [5,6,4]&lt;/code&gt; actually represents the number &lt;strong&gt;465&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our goal is to &lt;strong&gt;add these two numbers&lt;/strong&gt; (342 + 465) and return their &lt;strong&gt;sum&lt;/strong&gt; (807) also as a linked list in reverse order: &lt;code&gt;[7,0,8]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's look at the examples:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;br&gt;
Input: &lt;code&gt;l1 = [2,4,3]&lt;/code&gt; (342), &lt;code&gt;l2 = [5,6,4]&lt;/code&gt; (465)&lt;br&gt;
Output: &lt;code&gt;[7,0,8]&lt;/code&gt; (807)&lt;br&gt;
Explanation: 2 + 5 = 7. 4 + 6 = 10 (0 with carry 1). 3 + 4 + 1 (carry) = 8. So, [7, 0, 8].&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;br&gt;
Input: &lt;code&gt;l1 = [0]&lt;/code&gt;, &lt;code&gt;l2 = [0]&lt;/code&gt;&lt;br&gt;
Output: &lt;code&gt;[0]&lt;/code&gt;&lt;br&gt;
Explanation: 0 + 0 = 0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;br&gt;
Input: &lt;code&gt;l1 = [9,9,9,9,9,9,9]&lt;/code&gt;, &lt;code&gt;l2 = [9,9,9,9]&lt;/code&gt;&lt;br&gt;
Output: &lt;code&gt;[8,9,9,9,0,0,0,1]&lt;/code&gt;&lt;br&gt;
Explanation: This one shows longer lists and the need to handle a final carry! 9,999,999 + 9,999 = 10,009,998.&lt;/p&gt;


&lt;h3&gt;
  
  
  The "Aha!" Moment: Mimicking Manual Addition 💡
&lt;/h3&gt;

&lt;p&gt;The key to solving this problem lies in realizing that since the digits are already in &lt;em&gt;reverse order&lt;/em&gt;, the head of each linked list contains the &lt;strong&gt;least significant digit&lt;/strong&gt; (the "ones" place). This is exactly where we start when we add numbers by hand!&lt;/p&gt;

&lt;p&gt;So, the "aha!" moment is: &lt;strong&gt;we can simply iterate through both linked lists simultaneously, adding digits just like we would with pen and paper.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For each "place value":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add the corresponding digits from &lt;code&gt;l1&lt;/code&gt; and &lt;code&gt;l2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Don't forget to add any &lt;code&gt;carry&lt;/code&gt; from the previous addition!&lt;/li&gt;
&lt;li&gt; The sum of these three numbers (digit1 + digit2 + carry) will give us a &lt;code&gt;total_sum&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; The new digit for our result list will be &lt;code&gt;total_sum % 10&lt;/code&gt; (the remainder when divided by 10).&lt;/li&gt;
&lt;li&gt; The new &lt;code&gt;carry&lt;/code&gt; for the next iteration will be &lt;code&gt;total_sum // 10&lt;/code&gt; (the quotient when divided by 10).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We continue this process until we've gone through both lists &lt;em&gt;and&lt;/em&gt; handled any final carry.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Step-by-Step Approach 🚶‍♂️
&lt;/h3&gt;

&lt;p&gt;Let's break down the logic into concrete steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Initialize a Dummy Head:&lt;/strong&gt; Create a &lt;code&gt;dummy&lt;/code&gt; node. This is a common trick with linked lists! It acts as a placeholder for the beginning of our result list. We'll eventually return &lt;code&gt;dummy.next&lt;/code&gt; to skip this placeholder.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Current Pointer for Result:&lt;/strong&gt; Create a &lt;code&gt;res&lt;/code&gt; pointer and point it to &lt;code&gt;dummy&lt;/code&gt;. This &lt;code&gt;res&lt;/code&gt; pointer will move along as we build our new linked list.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Initialize Carry:&lt;/strong&gt; Set a &lt;code&gt;carry&lt;/code&gt; variable to &lt;code&gt;0&lt;/code&gt;. This will store any carry-over digit from our additions.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Loop Until Done:&lt;/strong&gt; We need to keep adding as long as there are digits in &lt;code&gt;l1&lt;/code&gt;, digits in &lt;code&gt;l2&lt;/code&gt;, or a &lt;code&gt;carry&lt;/code&gt; remaining. So, our loop condition will be &lt;code&gt;while l1 or l2 or carry:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Get Current Digits:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;l1&lt;/code&gt; exists, get its &lt;code&gt;val&lt;/code&gt;. Otherwise, consider it &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;l2&lt;/code&gt; exists, get its &lt;code&gt;val&lt;/code&gt;. Otherwise, consider it &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  This handles lists of unequal lengths gracefully.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Calculate Sum:&lt;/strong&gt; &lt;code&gt;total_sum = val1 + val2 + carry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;New Digit and New Carry:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;digit&lt;/code&gt; for our new node is &lt;code&gt;total_sum % 10&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;carry&lt;/code&gt; for the next iteration is &lt;code&gt;total_sum // 10&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Create and Append New Node:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new &lt;code&gt;ListNode&lt;/code&gt; with the calculated &lt;code&gt;digit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Append this new node to our result list: &lt;code&gt;res.next = new_node&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Move our &lt;code&gt;res&lt;/code&gt; pointer forward: &lt;code&gt;res = res.next&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Advance Input Pointers:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  If &lt;code&gt;l1&lt;/code&gt; is not &lt;code&gt;None&lt;/code&gt;, move &lt;code&gt;l1 = l1.next&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;l2&lt;/code&gt; is not &lt;code&gt;None&lt;/code&gt;, move &lt;code&gt;l2 = l2.next&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return Result:&lt;/strong&gt; Once the loop finishes, return &lt;code&gt;dummy.next&lt;/code&gt;. This skips our initial placeholder node and gives us the actual head of our sum list.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach perfectly mimics how we'd add numbers by hand, ensuring we handle carries and lists of different lengths.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Code 🧑‍💻
&lt;/h3&gt;

&lt;p&gt;Here's the Python implementation based on our approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Definition for singly-linked list.
# This part is usually provided by LeetCode or you define it yourself.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addTwoNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;

        &lt;span class="c1"&gt;# 1. Initialize a dummy head for the result list
&lt;/span&gt;        &lt;span class="n"&gt;dummy_head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# 2. 'current' pointer to build the result list
&lt;/span&gt;        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dummy_head&lt;/span&gt; 

        &lt;span class="c1"&gt;# 3. Initialize carry to 0
&lt;/span&gt;        &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# 4. Loop as long as there are digits in either list OR a carry remains
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 5. Get current digits (or 0 if list is exhausted)
&lt;/span&gt;            &lt;span class="n"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;val2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

            &lt;span class="c1"&gt;# 6. Calculate the total sum for the current position
&lt;/span&gt;            &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;val2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;

            &lt;span class="c1"&gt;# 7. Determine the digit for the current node and the new carry
&lt;/span&gt;            &lt;span class="n"&gt;new_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
            &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

            &lt;span class="c1"&gt;# 8. Create a new node and append it to our result list
&lt;/span&gt;            &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Move the 'current' pointer forward
&lt;/span&gt;            &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

            &lt;span class="c1"&gt;# 9. Advance input list pointers if they exist
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

        &lt;span class="c1"&gt;# 10. Return the actual head of the sum list (skipping the dummy_head)
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dummy_head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Time &amp;amp; Space Complexity Analysis ⏱️📏
&lt;/h3&gt;

&lt;p&gt;Understanding how much time and memory your solution uses is crucial for competitive programming!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(max(N, M))&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Where &lt;code&gt;N&lt;/code&gt; is the number of nodes in &lt;code&gt;l1&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; is the number of nodes in &lt;code&gt;l2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  We iterate through both linked lists at most once. The loop continues for a number of iterations equal to the length of the longer list, plus potentially one more if there's a final carry. Hence, the time taken scales linearly with the length of the longer input list.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(max(N, M))&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We create a new linked list to store the sum. In the worst case (e.g., adding two numbers like &lt;code&gt;[9,9,9]&lt;/code&gt; and &lt;code&gt;[1]&lt;/code&gt;), the result list can be one node longer than the longer input list (&lt;code&gt;[0,0,0,1]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Therefore, the space used to store the result scales linearly with the length of the longer input list.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Takeaways ✨
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Simulate Manual Processes:&lt;/strong&gt; Many problems, especially arithmetic ones, can be solved by translating your "pen-and-paper" method into code.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Power of a Dummy Node:&lt;/strong&gt; A dummy head node is a fantastic pattern for simplifying linked list operations, especially when you're building a new list or might need to modify the original head. It avoids annoying edge cases where you'd have to handle the first node creation separately.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Handling Carries and Unequal Lengths:&lt;/strong&gt; This problem is a great example of how to manage state (the &lt;code&gt;carry&lt;/code&gt;) between iterations and gracefully handle inputs of different sizes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Linked Lists for Big Numbers:&lt;/strong&gt; Linked lists are often used in computer science to represent numbers of arbitrary length, exceeding what standard integer types can hold.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congratulations! You've just walked through a fundamental LeetCode problem, learned about linked lists, and developed a solid approach. Keep practicing, and you'll be crushing those interviews in no time!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Authored by p1Hzd8mRM8. Published on 2026-05-16 22:58:14.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 2. Add Two Numbers</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 16:58:02 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-2-add-two-numbers-1k6i</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-2-add-two-numbers-1k6i</guid>
      <description>&lt;h1&gt;
  
  
  Unleash Your Inner Mathematician: Adding Numbers with Linked Lists (LeetCode #2)
&lt;/h1&gt;

&lt;p&gt;Hey awesome developers! 👋 Ever wondered how computers perform basic arithmetic with a twist? Today, we're diving into a classic LeetCode problem that might seem simple on the surface but introduces some fundamental data structures and algorithmic thinking: &lt;strong&gt;"Add Two Numbers"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This problem is a fantastic way to sharpen your skills with &lt;strong&gt;linked lists&lt;/strong&gt; and understand how to simulate everyday operations like addition programmatically. Don't worry if linked lists sound intimidating; we'll break it down piece by piece!&lt;/p&gt;




&lt;h3&gt;
  
  
  📚 Problem Explanation: Digits in Reverse!
&lt;/h3&gt;

&lt;p&gt;Imagine you have two numbers, but instead of seeing them as regular integers like &lt;code&gt;342&lt;/code&gt; or &lt;code&gt;465&lt;/code&gt;, their digits are stored in a special way: a &lt;strong&gt;linked list&lt;/strong&gt;, and in &lt;strong&gt;reverse order&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Each "node" in our linked list holds a single digit. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The number &lt;code&gt;342&lt;/code&gt; would be represented as a linked list: &lt;code&gt;2 -&amp;gt; 4 -&amp;gt; 3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  The number &lt;code&gt;465&lt;/code&gt; would be: &lt;code&gt;5 -&amp;gt; 6 -&amp;gt; 4&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our mission? To add these two numbers together, digit by digit, and return their sum as &lt;em&gt;another&lt;/em&gt; linked list, also in reverse order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's look at Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;l1 = [2,4,3]&lt;/code&gt; (represents 342)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;l2 = [5,6,4]&lt;/code&gt; (represents 465)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;[7,0,8]&lt;/code&gt; (represents 807)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See? &lt;code&gt;342 + 465 = 807&lt;/code&gt;. The &lt;code&gt;[7,0,8]&lt;/code&gt; linked list correctly gives us 807 in reverse!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few important rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The lists are &lt;em&gt;non-empty&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  Digits are non-negative (0-9).&lt;/li&gt;
&lt;li&gt;  No leading zeros (unless the number itself is 0, like &lt;code&gt;[0]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🤔 Intuition: How Do We Add Numbers By Hand?
&lt;/h3&gt;

&lt;p&gt;Before we jump into code, let's think about how &lt;em&gt;you&lt;/em&gt; add numbers manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  342
+ 465
-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Start from the rightmost digits:&lt;/strong&gt; &lt;code&gt;2 + 5 = 7&lt;/code&gt;. Write down &lt;code&gt;7&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Move to the next digits (tens place):&lt;/strong&gt; &lt;code&gt;4 + 6 = 10&lt;/code&gt;. Write down &lt;code&gt;0&lt;/code&gt;, and &lt;strong&gt;carry over&lt;/strong&gt; &lt;code&gt;1&lt;/code&gt; to the hundreds place.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Move to the next digits (hundreds place):&lt;/strong&gt; &lt;code&gt;3 + 4 + (the carried-over 1) = 8&lt;/code&gt;. Write down &lt;code&gt;8&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result is &lt;code&gt;807&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This "digit-by-digit, with a carry-over" strategy is exactly what we'll replicate with our linked lists! Since the digits are already in reverse order, it's like we're already starting from the rightmost digit (the units place)! This is a huge hint.&lt;/p&gt;




&lt;h3&gt;
  
  
  🪜 Approach: Step-by-Step with Linked Lists
&lt;/h3&gt;

&lt;p&gt;Our approach will mimic manual addition:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a &lt;code&gt;dummy&lt;/code&gt; node. This is a common trick in linked list problems. It acts as a placeholder for the head of our new list. We'll eventually return &lt;code&gt;dummy.next&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Create a &lt;code&gt;current&lt;/code&gt; pointer, initialized to &lt;code&gt;dummy&lt;/code&gt;. This pointer will help us build our result list by moving forward.&lt;/li&gt;
&lt;li&gt;  Initialize a &lt;code&gt;carry&lt;/code&gt; variable to &lt;code&gt;0&lt;/code&gt;. This will store any carry-over from the previous sum.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Iterate through the lists:&lt;/strong&gt; We need to keep adding digits as long as there are digits in &lt;em&gt;either&lt;/em&gt; &lt;code&gt;l1&lt;/code&gt; or &lt;code&gt;l2&lt;/code&gt;, or if there's still a &lt;code&gt;carry&lt;/code&gt; left over from a previous addition. This &lt;code&gt;while&lt;/code&gt; loop condition is crucial: &lt;code&gt;while l1 or l2 or carry:&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Calculate the sum for the current position:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Start &lt;code&gt;total_sum&lt;/code&gt; with the &lt;code&gt;carry&lt;/code&gt; from the previous step.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;l1&lt;/code&gt; is not &lt;code&gt;None&lt;/code&gt; (meaning there's a digit in the first number), add &lt;code&gt;l1.val&lt;/code&gt; to &lt;code&gt;total_sum&lt;/code&gt; and move &lt;code&gt;l1&lt;/code&gt; to its next node (&lt;code&gt;l1 = l1.next&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;l2&lt;/code&gt; is not &lt;code&gt;None&lt;/code&gt; (meaning there's a digit in the second number), add &lt;code&gt;l2.val&lt;/code&gt; to &lt;code&gt;total_sum&lt;/code&gt; and move &lt;code&gt;l2&lt;/code&gt; to its next node (&lt;code&gt;l2 = l2.next&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Determine the current digit and new carry:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The digit for our result list at the current position will be &lt;code&gt;total_sum % 10&lt;/code&gt; (the remainder after dividing by 10).&lt;/li&gt;
&lt;li&gt;  The new &lt;code&gt;carry&lt;/code&gt; will be &lt;code&gt;total_sum // 10&lt;/code&gt; (the integer division by 10).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build the result list:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new &lt;code&gt;ListNode&lt;/code&gt; with the calculated &lt;code&gt;digit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Append this new node to our result list: &lt;code&gt;current.next = new_node&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Move &lt;code&gt;current&lt;/code&gt; forward to this new node: &lt;code&gt;current = current.next&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return:&lt;/strong&gt; Once the loop finishes, we've built our entire sum list. Return &lt;code&gt;dummy.next&lt;/code&gt; to get the actual head of the sum list (skipping the initial placeholder &lt;code&gt;dummy&lt;/code&gt; node).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process continues until both input lists are exhausted AND there's no carry left.&lt;/p&gt;




&lt;h3&gt;
  
  
  💻 Code: Bringing It to Life (Python)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Definition for singly-linked list.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addTwoNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="c1"&gt;# Create a dummy node to simplify handling the head of the result list
&lt;/span&gt;        &lt;span class="n"&gt;dummy_head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# 'current' pointer will build our new linked list
&lt;/span&gt;        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dummy_head&lt;/span&gt;

        &lt;span class="c1"&gt;# Initialize carry to 0
&lt;/span&gt;        &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Loop as long as there are digits in either list or a carry exists
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Get the value from l1 (or 0 if l1 is exhausted)
&lt;/span&gt;            &lt;span class="n"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="c1"&gt;# Get the value from l2 (or 0 if l2 is exhausted)
&lt;/span&gt;            &lt;span class="n"&gt;val2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

            &lt;span class="c1"&gt;# Calculate the total sum for the current position
&lt;/span&gt;            &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;val2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;

            &lt;span class="c1"&gt;# Determine the digit for the new node (units place of total_sum)
&lt;/span&gt;            &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
            &lt;span class="c1"&gt;# Determine the new carry (tens place of total_sum)
&lt;/span&gt;            &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_sum&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

            &lt;span class="c1"&gt;# Create a new node with the calculated digit
&lt;/span&gt;            &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Move our 'current' pointer forward to the new node
&lt;/span&gt;            &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

            &lt;span class="c1"&gt;# Move l1 and l2 pointers forward if they are not exhausted
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;l1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

        &lt;span class="c1"&gt;# The first node (dummy_head) was just a placeholder.
&lt;/span&gt;        &lt;span class="c1"&gt;# The actual result list starts from dummy_head.next.
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dummy_head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⏱️ Time &amp;amp; Space Complexity Analysis
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt; O(max(m, n))&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;m&lt;/code&gt; is the number of nodes in &lt;code&gt;l1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;n&lt;/code&gt; is the number of nodes in &lt;code&gt;l2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  We iterate through both linked lists exactly once. The loop runs for a number of times proportional to the length of the longer list. This makes the time complexity linear with respect to the length of the longer input list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt; O(max(m, n))&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the worst-case scenario, the resulting linked list can have &lt;code&gt;max(m, n) + 1&lt;/code&gt; nodes (if there's a final carry-over). We are creating a new linked list to store the sum. Therefore, the space complexity is also linear with respect to the length of the longer input list.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🌟 Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Linked Lists for Arithmetic:&lt;/strong&gt; This problem beautifully demonstrates how linked lists can be used to represent and manipulate numbers, especially useful when dealing with very large numbers that might exceed standard integer types.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The "Dummy Node" Trick:&lt;/strong&gt; Using a &lt;code&gt;dummy_head&lt;/code&gt; node is a super common and effective pattern in linked list problems. It simplifies code by always having a node to attach to, eliminating special checks for an empty result list or when adding the very first node.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Carry Handling:&lt;/strong&gt; Understanding how to manage the &lt;code&gt;carry&lt;/code&gt; digit is fundamental to correctly implementing addition, whether manually or programmatically.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Simulating Manual Processes:&lt;/strong&gt; Many algorithmic problems can be solved by breaking them down into steps that mimic how we would solve them in real life.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This problem is a fantastic stepping stone for more complex linked list manipulations and numerical algorithms. Keep practicing, and you'll be a LeetCode master in no time! Happy coding!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Submission Details:&lt;/strong&gt;&lt;br&gt;
Author Account: p1Hzd8mRM8&lt;br&gt;
Time Published: 2026-05-16 22:27:48&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LeetCode Solution: 1. Two Sum</title>
      <dc:creator>Hommies</dc:creator>
      <pubDate>Sat, 16 May 2026 16:56:40 +0000</pubDate>
      <link>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-1-two-sum-2eh9</link>
      <guid>https://forem.com/hommies_fcbf2afe8ddb0c2a7/leetcode-solution-1-two-sum-2eh9</guid>
      <description>&lt;h1&gt;
  
  
  The OG LeetCode Challenge: Cracking Two Sum with Python!
&lt;/h1&gt;

&lt;p&gt;Hey there, future coding rockstars! 👋&lt;/p&gt;

&lt;p&gt;Ever wondered what the very first problem on LeetCode is? It's a true classic, a rite of passage for many, and a fantastic way to introduce fundamental data structures and algorithms. Today, we're diving into &lt;strong&gt;Two Sum&lt;/strong&gt;! Don't let the "easy" tag fool you; mastering this problem helps build crucial problem-solving muscles.&lt;/p&gt;

&lt;p&gt;Let's break it down together!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧐 What's the Problem All About? (Problem Explanation)
&lt;/h2&gt;

&lt;p&gt;Imagine you're given a list of numbers, like &lt;code&gt;[2, 7, 11, 15]&lt;/code&gt;, and a specific target number, say &lt;code&gt;9&lt;/code&gt;. Your mission, should you choose to accept it, is to find &lt;em&gt;two different numbers&lt;/em&gt; in that list that add up to your target.&lt;/p&gt;

&lt;p&gt;Once you find them, you don't return the numbers themselves, but their &lt;em&gt;positions&lt;/em&gt; (their "indices") in the original list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Time!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;nums = [2, 7, 11, 15]&lt;/code&gt;, &lt;code&gt;target = 9&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Think:&lt;/strong&gt; Can we find two numbers that sum to 9?

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;2 + 7 = 9&lt;/code&gt;! Bingo!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;[0, 1]&lt;/code&gt; (Because 2 is at index 0, and 7 is at index 1)&lt;/li&gt;

&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;nums = [3, 2, 4]&lt;/code&gt;, &lt;code&gt;target = 6&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Think:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;3 + 2 = 5&lt;/code&gt; (Nope)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;3 + 4 = 7&lt;/code&gt; (Nope)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;2 + 4 = 6&lt;/code&gt;! Yes!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;[1, 2]&lt;/code&gt; (2 is at index 1, 4 is at index 2)&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key things to remember:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You'll always find &lt;em&gt;exactly one&lt;/em&gt; solution.&lt;/li&gt;
&lt;li&gt;  You can't use the same number twice (e.g., if &lt;code&gt;nums&lt;/code&gt; had &lt;code&gt;3&lt;/code&gt; and &lt;code&gt;target&lt;/code&gt; was &lt;code&gt;6&lt;/code&gt;, you couldn't use the &lt;em&gt;same&lt;/em&gt; &lt;code&gt;3&lt;/code&gt; to make &lt;code&gt;3+3&lt;/code&gt;). If there are two &lt;code&gt;3&lt;/code&gt;s, you use both distinct &lt;code&gt;3&lt;/code&gt;s.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤔 Your "Aha!" Moment (Intuition)
&lt;/h2&gt;

&lt;p&gt;How would you solve this as a human, without a computer?&lt;/p&gt;

&lt;p&gt;You might pick the first number (&lt;code&gt;2&lt;/code&gt; from &lt;code&gt;[2, 7, 11, 15]&lt;/code&gt;), then look at &lt;em&gt;every other number&lt;/em&gt; to see if it adds up to &lt;code&gt;9&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;2 + 7 = 9&lt;/code&gt; (Found it!)&lt;/li&gt;
&lt;li&gt;  If not, you'd try &lt;code&gt;2 + 11&lt;/code&gt;, &lt;code&gt;2 + 15&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  If &lt;code&gt;2&lt;/code&gt; didn't work with any other number, you'd move to the next number (&lt;code&gt;7&lt;/code&gt;) and repeat the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what we call a &lt;strong&gt;brute-force&lt;/strong&gt; approach. It works, but it can be slow for very long lists. For every number, you're looking at almost all other numbers. If there are &lt;code&gt;N&lt;/code&gt; numbers, you might do &lt;code&gt;N * N&lt;/code&gt; (or &lt;code&gt;N^2&lt;/code&gt;) checks in the worst case. Can we do better?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Smarter Way: What are we &lt;em&gt;really&lt;/em&gt; looking for?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say we pick a number from our list, &lt;code&gt;nums[i]&lt;/code&gt;. We know we need another number, let's call it &lt;code&gt;complement&lt;/code&gt;, such that:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nums[i] + complement = target&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This means &lt;code&gt;complement = target - nums[i]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, for each &lt;code&gt;nums[i]&lt;/code&gt; we encounter, we don't need to try &lt;em&gt;every other number&lt;/em&gt;. We just need to quickly check if its &lt;em&gt;specific complement&lt;/em&gt; exists somewhere else in our list.&lt;/p&gt;

&lt;p&gt;How do we check for existence super fast? With a &lt;strong&gt;hash map&lt;/strong&gt; (or a &lt;code&gt;dictionary&lt;/code&gt; in Python)! A hash map allows us to store key-value pairs and look up keys almost instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The Game Plan (Approach)
&lt;/h2&gt;

&lt;p&gt;We'll use a &lt;strong&gt;two-pass hash map&lt;/strong&gt; approach. This means we'll go through our &lt;code&gt;nums&lt;/code&gt; list twice.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;First Pass: Build the Lookup Table&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We'll create an empty &lt;code&gt;hashmap&lt;/code&gt; (a Python dictionary).&lt;/li&gt;
&lt;li&gt;  We iterate through &lt;code&gt;nums&lt;/code&gt; one time. For each number &lt;code&gt;nums[i]&lt;/code&gt; we see, we'll store it in our &lt;code&gt;hashmap&lt;/code&gt; along with its index &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  So, our &lt;code&gt;hashmap&lt;/code&gt; will look something like &lt;code&gt;{number: index}&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;  Example &lt;code&gt;nums = [2, 7, 11, 15]&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;  After this pass, &lt;code&gt;hashmap&lt;/code&gt; might be: &lt;code&gt;{2: 0, 7: 1, 11: 2, 15: 3}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Second Pass: Find the Complement&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Now, we iterate through &lt;code&gt;nums&lt;/code&gt; &lt;em&gt;again&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  For each number &lt;code&gt;nums[i]&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;  Calculate its &lt;code&gt;complement&lt;/code&gt;: &lt;code&gt;complement = target - nums[i]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Check if this &lt;code&gt;complement&lt;/code&gt; exists as a key in our &lt;code&gt;hashmap&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Crucially&lt;/strong&gt;, we also need to make sure that the index associated with the &lt;code&gt;complement&lt;/code&gt; in the &lt;code&gt;hashmap&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; the current index &lt;code&gt;i&lt;/code&gt;. This prevents us from trying to use the same number twice.&lt;/li&gt;
&lt;li&gt;  If both conditions are met (complement found, and it's a different number), we've found our pair! Return &lt;code&gt;[i, hashmap[complement]]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because the problem guarantees exactly one solution, we know we'll find our answer and return from the function during this second pass.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Let's Code!
&lt;/h2&gt;

&lt;p&gt;Here's the Python solution implementing the two-pass hash map approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;twoSum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="c1"&gt;# Step 1: Initialize a hash map (Python dictionary) to store numbers and their indices
&lt;/span&gt;        &lt;span class="n"&gt;hashmap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; 

        &lt;span class="c1"&gt;# First Pass: Populate the hash map
&lt;/span&gt;        &lt;span class="c1"&gt;# We iterate through the array once to store each number and its index.
&lt;/span&gt;        &lt;span class="c1"&gt;# This makes subsequent lookups much faster.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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="n"&gt;hashmap&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="c1"&gt;# Store: {number: index}
&lt;/span&gt;
        &lt;span class="c1"&gt;# Second Pass: Find the complement
&lt;/span&gt;        &lt;span class="c1"&gt;# Now, we iterate through the array again. For each number, we calculate
&lt;/span&gt;        &lt;span class="c1"&gt;# what its 'complement' should be to reach the target.
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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="n"&gt;complement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;-&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;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="c1"&gt;# Check if the complement exists in our hash map:
&lt;/span&gt;            &lt;span class="c1"&gt;# - `complement in hashmap`: Is the required complement present in our stored numbers?
&lt;/span&gt;            &lt;span class="c1"&gt;# - `hashmap[complement] != i`: Is the complement not the current number itself (i.e., are their indices different)?
&lt;/span&gt;            &lt;span class="c1"&gt;#   This is important because we can't use the same element twice.
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;complement&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hashmap&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;hashmap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;complement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# If both conditions are true, we found our pair!
&lt;/span&gt;                &lt;span class="c1"&gt;# Return the index of the current number (i) and the index of its complement.
&lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashmap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;complement&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

        &lt;span class="c1"&gt;# This line should ideally not be reached based on the problem constraints
&lt;/span&gt;        &lt;span class="c1"&gt;# (which state that exactly one solution exists).
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⏰ Space and Time Efficiency (Complexity Analysis)
&lt;/h2&gt;

&lt;p&gt;Understanding how efficient your code is, especially for large inputs, is a core skill!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Complexity: O(n)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The first loop (&lt;code&gt;for i in range(len(nums))&lt;/code&gt;) iterates &lt;code&gt;n&lt;/code&gt; times to populate the hash map. On average, inserting an element into a hash map takes &lt;code&gt;O(1)&lt;/code&gt; time. So, the first pass is &lt;code&gt;O(n)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The second loop (&lt;code&gt;for i in range(len(nums))&lt;/code&gt;) also iterates &lt;code&gt;n&lt;/code&gt; times. Inside this loop, calculating the &lt;code&gt;complement&lt;/code&gt; is &lt;code&gt;O(1)&lt;/code&gt;, and looking up an element in a hash map takes &lt;code&gt;O(1)&lt;/code&gt; time on average. So, the second pass is also &lt;code&gt;O(n)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Adding them up, &lt;code&gt;O(n) + O(n) = O(2n)&lt;/code&gt;, which simplifies to &lt;strong&gt;O(n)&lt;/strong&gt;. This is much faster than the &lt;code&gt;O(n^2)&lt;/code&gt; brute-force approach!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(n)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In the worst-case scenario, we might have to store all &lt;code&gt;n&lt;/code&gt; numbers and their indices in our &lt;code&gt;hashmap&lt;/code&gt;. Therefore, the space required grows linearly with the number of elements in the input array.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Hash Maps are Your Friends:&lt;/strong&gt; For problems involving quick lookups or checking for the existence of elements, hash maps (dictionaries) are incredibly powerful. They can transform a slow &lt;code&gt;O(n)&lt;/code&gt; lookup into an average &lt;code&gt;O(1)&lt;/code&gt; operation!&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Think Complements:&lt;/strong&gt; Many problems can be simplified by rephrasing what you're looking for. Instead of "find two numbers that sum to X", think "for each number, find its 'complement' (X - number)".&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Optimize Iterations:&lt;/strong&gt; While a brute-force approach (nested loops, &lt;code&gt;O(n^2)&lt;/code&gt;) might be your first thought, always consider if you can reduce the number of passes or operations using a suitable data structure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This problem, despite being "easy," introduces you to a fundamental pattern used in many more complex LeetCode challenges. Keep practicing, and you'll be solving harder problems in no time!&lt;/p&gt;

&lt;p&gt;Happy coding! ✨&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Author Account: p1Hzd8mRM8&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Publishing Time: 2026-05-16 22:26:22&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
