Problem Statement
Given a string s, return the length of the longest substring without repeating characters.
A substring is a contiguous sequence of characters within a string.
Example 1
Input: s = "zxyzxyz"
Output: 3
Explanation:
The longest substring without repeating characters is "xyz".Example 2
Input: s = "xxxx"
Output: 1Constraints
0 <= s.length <= 1000sconsists of printable ASCII characters.
Intuition
The goal is to find the longest continuous part of the string where every character is unique.
For example,
s = "abcabcbb"Possible substrings without repeating characters are:
"a" -> 1
"ab" -> 2
"abc" -> 3
"bca" -> 3
"cab" -> 3The answer is 3.
There are multiple ways to solve this problem, each improving upon the previous one.
Solution 1: Brute Force
Idea
Start from every index and keep extending the substring until a duplicate character appears.
To quickly check whether we’ve already seen a character, we use a set.
For every starting position:
- Create an empty set.
- Move forward character by character.
- If the character is already in the set, stop.
- Otherwise, insert it and update the maximum length.
Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
count = 0
for i in range(len(s)):
charSet = set()
for j in range(i, len(s)):
if s[j] in charSet:
break
charSet.add(s[j])
count = max(count, len(charSet))
return countDry Run
Let’s use
s = "zxyzxyz"Start at index 0
{}
↓
z -> {z} length = 1
x -> {z,x} length = 2
y -> {z,x,y} length = 3
z -> duplicate → stopMaximum = 3
Start at index 1
{}
↓
x -> {x}
y -> {x,y}
z -> {x,y,z}
x -> duplicateMaximum remains 3
The same process repeats for every index.
Complexity Analysis
Time Complexity
The outer loop runs n times.
For every starting position, the inner loop may also scan up to n characters.
O(n²)Space Complexity
The set can contain at most every unique character.
O(min(n, charset))For ASCII characters, this is effectively constant, but generally we write:
O(n)Solution 2: Sliding Window (Optimal)
The brute-force solution repeats a lot of work.
Suppose we’ve already examined the substring:
xyzWhen we encounter another x, instead of starting over, we can simply shrink the current window from the left until the duplicate is removed.
This is exactly what the Sliding Window technique does.
Idea
Maintain a window with two pointers:
l→ left boundaryr→ right boundary
The window always contains unique characters only.
For every character:
- If it’s new, expand the window.
- If it’s already inside the window, remove characters from the left until the duplicate disappears.
- Update the maximum window size.
Visualization
Consider
s = "zxyzxyz"Initially
Window = ""Step 1
l
↓
z
↑
rWindow:
zLength = 1
Step 2
l
↓
zx
↑
rWindow:
zxLength = 2
Step 3
l
↓
zxy
↑
rWindow:
zxyLength = 3
Step 4
Next character is another z.
Current window:
zxySince z already exists:
Remove characters from the left.
Remove first z
xyNow insert new z
xyzThe window is valid again.
Maximum length remains 3.
Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
charSet = set()
l = 0
count = 0
for r in range(len(s)):
while s[r] in charSet:
charSet.remove(s[l])
l += 1
charSet.add(s[r])
count = max(count, r - l + 1)
return countWhy Does This Work?
The sliding window always satisfies one important condition:
Every character inside the window is unique.
Whenever a duplicate appears:
- We don’t discard the whole substring.
- We only remove enough characters from the left to eliminate the duplicate.
- Then we continue expanding.
Each character is:
- Added to the set once
- Removed from the set once
This is why the algorithm runs in linear time.
Complexity Analysis
Time Complexity
Although there is a while loop inside the for loop, each character enters and leaves the window at most once.
O(n)Space Complexity
The set stores only unique characters currently in the window.
O(min(n, charset))or simply
O(n)Brute Force vs Sliding Window
Approach | Time | Space |
|---|---|---|
Brute Force | O(n²) | O(n) |
Sliding Window | O(n) | O(n) |
The sliding window solution avoids reprocessing characters, making it much more efficient for longer strings.
Key Takeaways
- A set is perfect for checking duplicates in constant time.
- The brute-force solution checks every possible substring but repeats a lot of work.
- The sliding window technique maintains a valid substring by expanding to the right and shrinking from the left only when necessary.
- Since every character is processed at most twice (once when added and once when removed), the optimal solution runs in O(n) time.
Sliding Window is one of the most important techniques for string and array problems, and mastering this pattern will help solve many interview questions efficiently.