3. Longest Substring Without Repeating Characters
mediumAsked at IBMLongest Substring Without Repeating Characters is IBM's sliding-window screener. The interviewer is grading whether you reach for the dynamic-window technique with a last-seen index map, whether you handle the 'jump the left pointer' optimization, and whether you ship O(n) with a single pass.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in IBM loops.
- Glassdoor (2026-Q1)— IBM SWE-2 / SWE-3 onsite recurring problem.
- LeetCode (2026-Q1)— Top-25 IBM-tagged problem (medium tier).
- GeeksforGeeks (2025-12)— Listed in IBM interview-experience archive.
Problem
Given a string s, find the length of the longest substring without repeating characters.
Constraints
0 <= s.length <= 5 * 10^4s consists of English letters, digits, symbols and spaces.
Examples
Example 1
s = "abcabcbb"3Explanation: The answer is 'abc' with length 3.
Example 2
s = "bbbbb"1Example 3
s = "pwwkew"3Explanation: 'wke' has length 3; 'pwke' is a subsequence, not a substring.
Approaches
1. Brute force — check every substring
Iterate over all (i, j) pairs, check whether s[i..j] has duplicates.
- Time
- O(n^3)
- Space
- O(min(n, alphabet))
function lengthOfLongestSubstringBrute(s) {
const hasUnique = (str) => {
const seen = new Set();
for (const ch of str) {
if (seen.has(ch)) return false;
seen.add(ch);
}
return true;
};
let best = 0;
for (let i = 0; i < s.length; i++) {
for (let j = i + 1; j <= s.length; j++) {
if (hasUnique(s.slice(i, j))) best = Math.max(best, j - i);
}
}
return best;
}Tradeoff: Cubic time. At n=5*10^4 it's 10^14 operations — times out by a factor of 10^7. Useful only as the starting point to optimize away.
2. Sliding window with set (intermediate)
Two pointers (left, right). Expand right adding chars; on duplicate, shrink left one step at a time until duplicate is gone.
- Time
- O(n)
- Space
- O(min(n, alphabet))
function lengthOfLongestSubstringSet(s) {
const seen = new Set();
let left = 0;
let best = 0;
for (let right = 0; right < s.length; right++) {
while (seen.has(s[right])) {
seen.delete(s[left]);
left++;
}
seen.add(s[right]);
best = Math.max(best, right - left + 1);
}
return best;
}Tradeoff: O(n) amortized because each character is added and removed at most once. Cleanest mental model — show this version first on the whiteboard.
3. Sliding window with last-seen index map (optimal)
Map each char to its most recent index. On duplicate, jump left directly past the previous occurrence.
- Time
- O(n)
- Space
- O(min(n, alphabet))
function lengthOfLongestSubstring(s) {
const lastSeen = new Map();
let left = 0;
let best = 0;
for (let right = 0; right < s.length; right++) {
const ch = s[right];
if (lastSeen.has(ch) && lastSeen.get(ch) >= left) {
left = lastSeen.get(ch) + 1;
}
lastSeen.set(ch, right);
best = Math.max(best, right - left + 1);
}
return best;
}Tradeoff: Single pass with O(1) inner work per character. Jumping left in one step (instead of incrementing) is the micro-optimization that earns the senior-bar checkbox. The `>= left` guard is critical — stale entries below `left` must be ignored.
IBM-specific tips
IBM grades the sliding-window pattern recognition AND the 'jump the left pointer' optimization. State 'I'll jump left past the previous occurrence in one step instead of advancing one-by-one' before coding the last-seen-map version. Watch the stale-entry guard — `lastSeen.get(ch) >= left` is the line candidates most often forget, leading to incorrect window contractions.
Common mistakes
- Forgetting the `>= left` guard — incorrectly contracts the window based on entries outside the current window.
- Initializing best = 1 instead of 0 — fails for empty string input.
- Using `right - left` instead of `right - left + 1` for window size — off-by-one.
- Using a fixed-size 128 array assuming ASCII-only input when the problem allows Unicode — switch to Map.
- Updating lastSeen BEFORE the duplicate check — corrupts the previous-position info.
Follow-up questions
An interviewer at IBM may pivot to one of these next:
- Longest Substring with At Most K Distinct Characters (LeetCode 340).
- Longest Substring with At Most Two Distinct Characters (LeetCode 159).
- Minimum Window Substring (LeetCode 76).
- What if the alphabet is restricted to lowercase ASCII? (Swap Map for a 26-int array — same logic.)
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why is the sliding-window technique O(n) amortized?
Because each character is touched at most twice — once when right advances past it, once when left advances past it. Total operations across all iterations is bounded by 2n, hence O(n). The naive version touches each character up to n times, which is why it's cubic.
Why does IBM prefer the index-jump variant?
Because it's strictly better — same complexity class but lower constant factor (one jump vs up to k increments). On a senior interview loop, shipping the index-jump version signals you've internalized the pattern, not just memorized the set-based shrink loop.
Free learning resources
Curated free links for this problem.
Practice these live with InterviewChamp.AI
Drill Longest Substring Without Repeating Characters and other IBM interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →