Files
codetutor/backend/data/questions/longest-substring-without-repeating.yaml

115 lines
3.9 KiB
YAML

title: Longest Substring Without Repeating Characters
slug: longest-substring-without-repeating
difficulty: medium
leetcode_id: 3
leetcode_url: https://leetcode.com/problems/longest-substring-without-repeating-characters/
categories:
- strings
- hash-tables
patterns:
- sliding-window
description: |
Given a string `s`, find the length of the longest substring without repeating characters.
constraints: |
- 0 <= s.length <= 5 * 10^4
- s consists of English letters, digits, symbols and spaces
examples:
- input: 's = "abcabcbb"'
output: "3"
explanation: "The answer is 'abc', with length 3."
- input: 's = "bbbbb"'
output: "1"
explanation: "The answer is 'b', with length 1."
- input: 's = "pwwkew"'
output: "3"
explanation: "The answer is 'wke', with length 3."
explanation:
approach: |
1. Use a sliding window with left and right pointers
2. Maintain a set of characters in the current window
3. Expand right pointer, adding characters to the set
4. When a duplicate is found, shrink from left until duplicate is removed
5. Track maximum window size throughout
intuition: |
We're looking for the longest contiguous substring where all characters are unique.
A sliding window naturally represents a substring.
When we encounter a duplicate, the current window is invalid. Instead of restarting
from scratch, we shrink the window from the left until the duplicate is removed.
This way, we never revisit characters unnecessarily.
common_pitfalls:
- title: Resetting the window incorrectly
description: |
When finding a duplicate, don't start over from the next character.
Instead, shrink from the left until the duplicate is removed.
wrong_approach: "left = right when duplicate found"
correct_approach: "Increment left until duplicate is out of window"
- title: Not handling empty string
description: |
An empty string should return 0. Make sure the algorithm handles this.
- title: Off-by-one in length calculation
description: |
Window length is right - left + 1, or just track max before removing.
key_takeaways:
- Sliding window is ideal for substring problems with constraints
- Use a set or map to track elements in current window
- Shrinking from one end maintains the contiguous property
- This pattern appears in many "longest/shortest with constraint" problems
time_complexity: "O(n)"
space_complexity: "O(min(m, n))"
complexity_explanation: |
Time: Each character is visited at most twice (once by right, once by left).
Space: The set holds at most min(n, m) characters where m is the charset size.
solutions:
- approach_name: Sliding Window with Set (Optimal)
is_optimal: true
code: |
def length_of_longest_substring(s: str) -> int:
char_set = set()
left = 0
max_length = 0
for right in range(len(s)):
while s[right] in char_set:
char_set.remove(s[left])
left += 1
char_set.add(s[right])
max_length = max(max_length, right - left + 1)
return max_length
explanation: |
Expand window by moving right pointer.
When duplicate found, shrink from left until window is valid again.
- approach_name: Optimized with Hash Map
is_optimal: true
code: |
def length_of_longest_substring(s: str) -> int:
char_index = {}
left = 0
max_length = 0
for right, char in enumerate(s):
if char in char_index and char_index[char] >= left:
left = char_index[char] + 1
char_index[char] = right
max_length = max(max_length, right - left + 1)
return max_length
explanation: |
Store the last index of each character.
Jump left pointer directly past the duplicate instead of shrinking one by one.