Find the length of the longest substring without repeating characters.
Use a variable-size sliding window with a hash map that records the most recent index of each character. When the right pointer hits a character already in the window, jump the left pointer to one past that character's last position — skipping over the repeat in one move rather than crawling one step at a time.
How to think about it
When a string question asks for the longest (or shortest) stretch that satisfies some rule, the interviewer is fishing for a sliding window. The brute force — generate every substring and check each for repeats — is O(n²) substrings times an O(n) scan, hopelessly cubic. The window collapses all of that into a single walk across the string, and the thing they want to see is whether you can keep that window valid without ever scanning backward.
Picture a window [left, right] that always holds distinct characters. You push right forward one character at a time. The instant s[right] is a character already inside the window, you have to evict the old copy — but you don’t crawl left forward one step at a time hunting for it. You stored its index in a hash map, so you teleport left straight to one position past it. The window is clean again in a single move, and you never re-read a character. The one piece of bookkeeping is the guard: only jump if the stored index is actually inside the current window, because the map keeps old entries around even after left has moved past them.
A worked example
def length_of_longest_substring(s):
seen = {} # char -> most recent index
left = 0
best = 0
for right, ch in enumerate(s):
# jump left only if the repeat sits inside the current window
if ch in seen and seen[ch] >= left:
left = seen[ch] + 1
seen[ch] = right
best = max(best, right - left + 1)
return best
print(length_of_longest_substring("abcabcbb")) # "abc"
print(length_of_longest_substring("bbbbb")) # "b"
print(length_of_longest_substring("pwwkew")) # "wke"
print(length_of_longest_substring("")) # empty string
3
1
3
0
In "abcabcbb" the window grows to "abc", then every following character is a repeat, so left keeps jumping forward and the window never gets past length 3. "bbbbb" is all one letter — each new b shoves left right behind right, leaving a window of 1. "pwwkew" peaks at "wke", not "pwwke", because the second w resets the window. The empty string never enters the loop, so best stays 0.