Leetcode Diaries: Longest Substring Without Repeating Characters – No Duplicates Allowed 🚫
Hey again!
Today I solved another classic from the Leetcode hall of fame:
3. Longest Substring Without Repeating Characters — and wow, it’s one of those problems that hits both the brain and the backspace key hard at first!
Let’s break it down in plain English, walk through the logic, and look at both Python and Go solutions.
🧩 The Problem
Given a string
s
, find the length of the longest substring without repeating characters.
For example:
-
Input:
"abcabcbb"
-
Output:
3
-
Explanation: The longest substring without repeating characters is
"abc"
, which has length 3.
🐍 Python Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
seen = set()
left = 0
max_len = 0
for right in range(len(s)):
while s[right] in seen:
seen.remove(s[left])
left += 1
seen.add(s[right])
max_len = max(max_len, right - left + 1)
return max_len
⚙️ Golang Code
func lengthOfLongestSubstring(s string) int {
seen := make(map[byte]bool)
left, maxLen := 0, 0
for right := 0; right < len(s); right++ {
for seen[s[right]] {
delete(seen, s[left])
left++
}
seen[s[right]] = true
if right-left+1 > maxLen {
maxLen = right - left + 1
}
}
return maxLen
}
🧠 How It Works (Sliding Window Approach)
Both solutions use a technique called the sliding window, which is basically two pointers (left
and right
) sliding through the string to maintain a current substring without duplicates.
-
right
expands the window -
left
shrinks it if a duplicate is found -
A set/map keeps track of seen characters
🧪 Example Walkthrough – s = "abcabcbb"
Let’s go through it step-by-step:
Initial:
-
left = 0
,right = 0
,seen = {}
,max_len = 0
Step 1: s[0] = 'a'
-
Not in seen → Add it →
seen = {'a'}
-
Window:
'a'
→ length = 1 -
max_len = 1
Step 2: s[1] = 'b'
-
Not in seen → Add it →
seen = {'a', 'b'}
-
Window:
'ab'
→ length = 2 -
max_len = 2
Step 3: s[2] = 'c'
-
Not in seen → Add it →
seen = {'a', 'b', 'c'}
-
Window:
'abc'
→ length = 3 -
max_len = 3
Step 4: s[3] = 'a'
-
'a'
is in seen → Shrink from left-
Remove
'a'
→left = 1
,seen = {'b', 'c'}
-
-
Now add
'a'
again →seen = {'a', 'b', 'c'}
-
Window:
'bca'
→ length = 3 →max_len = 3
(no change)
Step 5: s[4] = 'b'
-
'b'
is in seen → Shrink:-
Remove
'b'
→left = 2
-
-
Add
'b'
→seen = {'a', 'b', 'c'}
-
Window:
'cab'
→ length = 3 →max_len = 3
Step 6: s[5] = 'c'
-
'c'
is in seen → Shrink:-
Remove
'c'
→left = 3
-
-
Add
'c'
→seen = {'a', 'b', 'c'}
-
Window:
'abc'
→ length = 3 →max_len = 3
Step 7: s[6] = 'b'
-
'b'
is in seen → Shrink:-
Remove
'a'
→left = 4
-
Remove
'b'
→left = 5
-
-
Add
'b'
→seen = {'c', 'b'}
-
Window:
'cb'
→ length = 2 →max_len = 3
Step 8: s[7] = 'b'
-
'b'
is in seen → Shrink:-
Remove
'c'
→left = 6
-
Remove
'b'
→left = 7
-
-
Add
'b'
→seen = {'b'}
-
Window:
'b'
→ length = 1 →max_len = 3
✅ Final Answer: 3
The longest substrings without repeating characters are:
"abc"
, "bca"
, "cab"
, all of length 3
.
💭 Final Thoughts
This problem teaches a powerful and reusable pattern—the sliding window. It's super helpful in string and array problems where we’re tracking a range with some constraint.
⚡ Takeaways
-
Use set/map to track characters
-
Two-pointer technique keeps it O(n)
-
Always update
max_len
after every successful window shift
That’s it for today! Another 🔥 problem checked off.
0 Comments