Longest Substring Without Repeating Characters
Difficulty: Medium
You're given a string. Find the length of the longest substring (a contiguous run of characters, not just any subset) that contains no repeated characters.
Examples
Input: s = "abcabcbb"
Output: 3
The longest run with no repeats is "abc", which has length 3.
Input: s = "bbbbb"
Output: 1
Every character repeats immediately, so the best you can do is a single character, "b".
Input: s = "pwwkew"
Output: 3
"wke" is the longest substring without repeats. Note "pwke" is not a valid answer because it is not contiguous in the original string.
Constraints
0 <= s.length <= 5 * 10^4
s consists of English letters, digits, symbols, and spaces.
Approach
A brute-force approach would check every possible substring, and for each one scan it to see if it has repeated characters. That's a lot of redundant scanning since substrings overlap heavily.
Instead, use a sliding window: keep two pointers, left and right, marking the current substring, plus a set of the characters currently inside that window. Move right forward one step at a time, adding characters to the set. If the character you're adding is already in the set, that means the window has a duplicate — so shrink the window from the left, removing characters, until the duplicate is gone. At every step, the window is duplicate-free, so its length is a candidate answer. This way each character is added and removed from the window at most once, giving a single pass overall.
Solutions
Brute Force — Check Every Substring
Try every start and end position, and for each candidate substring scan it to check whether all characters are unique. Simple, but re-scans overlapping substrings many times.
function lengthOfLongestSubstring(s) {
let best = 0;
for (let start = 0; start < s.length; start++) {
const seen = new Set();
for (let end = start; end < s.length; end++) {
if (seen.has(s[end])) {
break;
}
seen.add(s[end]);
best = Math.max(best, end - start + 1);
}
}
return best;
}Time: O(n²) · Space: O(min(n, alphabet size))
Optimal — Sliding Window with a Set
Grow the window by moving the right edge forward. Whenever the incoming character is already inside the window, shrink from the left until it isn't a duplicate anymore, then keep going.
function lengthOfLongestSubstring(s) {
const window = new Set();
let left = 0;
let best = 0;
for (let right = 0; right < s.length; right++) {
while (window.has(s[right])) {
window.delete(s[left]);
left++;
}
window.add(s[right]);
best = Math.max(best, right - left + 1);
}
return best;
}Time: O(n) · Space: O(min(n, alphabet size))