3. Longest Substring Without Repeating Characters
mediumAsked at CohereFind the length of the longest substring with all unique characters. Cohere asks this because sliding-window deduplication is core to tokenization span selection and context-window management in production language-model serving.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Cohere loops.
- Glassdoor (2026-Q1)— Cohere SWE and MLE candidates report this as one of the most common medium questions across all interview rounds.
- Blind (2025-11)— Consistently appears in Cohere interview prep threads as a must-solve sliding window problem.
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: "abc" has length 3.
Example 2
s = "bbbbb"1Explanation: "b" is the longest unique substring.
Example 3
s = "pwwkew"3Explanation: "wke" has length 3.
Approaches
1. Sliding window with Map
Use a Map to store the most recent index of each character. When a repeat is found, jump the left pointer past the previous occurrence. Update the max length on every iteration.
- Time
- O(n)
- Space
- O(min(n, alphabet))
function lengthOfLongestSubstring(s) {
const lastSeen = new Map();
let left = 0, maxLen = 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; // shrink window past the repeat
}
lastSeen.set(ch, right);
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}Tradeoff: O(n) single pass. The Map jump avoids redundant left-pointer increments and makes this faster than a Set-based shrink loop for long inputs.
2. Sliding window with Set
Maintain a Set of characters in the current window. When a repeat is encountered, shrink the window from the left until the repeat is removed.
- Time
- O(n)
- Space
- O(min(n, alphabet))
function lengthOfLongestSubstring(s) {
const seen = new Set();
let left = 0, maxLen = 0;
for (let right = 0; right < s.length; right++) {
while (seen.has(s[right])) {
seen.delete(s[left++]);
}
seen.add(s[right]);
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}Tradeoff: Simpler to reason about but the inner while loop makes it technically O(2n) in the worst case. Still O(n) overall, but the Map-jump approach avoids redundant iterations.
Cohere-specific tips
Cohere engineers regularly think about efficient windowing over token sequences. Frame the solution in terms of a streaming context window: 'My left and right pointers define the active context; on a collision I advance the left boundary to just after the previous occurrence — this models how a decoder discards stale context.' The Map-jump approach is preferred at Cohere because it avoids redundant deletions when handling large character spaces (e.g., Unicode).
Common mistakes
- Forgetting the guard lastSeen.get(ch) >= left — without it, stale Map entries from outside the window trigger incorrect left-pointer jumps.
- Returning right - left instead of right - left + 1 — off-by-one in window length calculation.
- Updating maxLen only when a new character is added, not on every iteration.
- Using string slicing to check uniqueness — O(n²) with extra allocations.
Follow-up questions
An interviewer at Cohere may pivot to one of these next:
- Longest Substring with At Most K Distinct Characters — extend the Map to count occurrences.
- Minimum Window Substring — find the smallest window containing all target characters.
- How would you track the longest unique-character span in a real-time token stream?
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why check lastSeen.get(ch) >= left?
Stale Map entries remain after the left pointer advances. Without the check, a character last seen before the current window would incorrectly trigger a left-pointer jump.
What is the alphabet size in the worst case?
For ASCII it is 128; for Unicode it can be much larger. Space complexity is O(min(n, |alphabet|)) — bounded by whichever is smaller.
Which approach should I code first?
The Map-jump approach — it is strictly more efficient and demonstrates a deeper understanding of why the Set approach does redundant work.
Practice these live with InterviewChamp.AI
Drill Longest Substring Without Repeating Characters and other Cohere interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →