Longest Substring Without Repeating Characters
Problem statement
Given a string s, find the longest contiguous run of characters in which no character appears twice, and return its length. The string can contain letters, digits, spaces and symbols, and it can be empty.
Examples
Example 1
Input: s = "deploydev"
Output: 7
Explanation: "ploydev" has seven different characters. Any longer stretch repeats a "d" or an "e".
Example 2
Input: s = "aaaa"
Output: 1
Explanation: Every stretch longer than one character repeats "a".
Hints
Approach
Use a variable-size sliding window [left, right] that always holds distinct characters, plus a map from each character to the last index where it appeared.
- Set
left = 0and an empty maplast. - For each
right, letch = s[right]. Ifchwas seen at an index>= left, it is inside the window, so movelefttolast[ch] + 1. - Record
last[ch] = rightand update the best lengthright - left + 1. - Return the best length.
The check last[ch] >= left matters: a character seen before the window started is not a duplicate. In "abba", when the final a arrives the window is "b" (starting at index 2), and the old a at index 0 must not pull left backwards.
A simpler variant keeps a set and moves left one step at a time while removing characters. It is also O(n), but does up to two passes over the string.
O(n)Space O(min(n, a))class Solution: def lengthOfLongestSubstring(self, s: str) -> int: last = {} # character -> last index seen left = 0 best = 0 for right, ch in enumerate(s): if ch in last and last[ch] >= left: left = last[ch] + 1 # jump past the earlier copy last[ch] = right best = max(best, right - left + 1) return bestFollow-up questions
- Return the substring itself, not just its length.
- Allow each character to appear at most twice in the window.
Frequently asked questions
It is the size of the character set. The map never holds more distinct characters than exist, so space is bounded by both the string length and the alphabet size.
Restarting from the repeated character's position throws away valid work and can miss answers. Moving left to just past the earlier copy keeps everything in between, which is still duplicate-free.
It is the standard test of the grow-and-shrink window pattern, which is how you answer questions like "the longest stretch of log lines with no repeated request ID" or "the longest run of deploys with no repeated host" in a single pass.