150NeetCode 150

16.Longest Substring Without Repeating Characters

MediumBlind 75Sliding Window ยท 2/6
LeetCode #3Video

Problem

Given a string s, return the length of the longest substring that contains no repeated characters.

A substring is a contiguous block of characters โ€” "pwke" is a subsequence of "pwwkew" but not a substring.

Examples

Input:  s = "abcabcbb"
Output: 3
Explanation: "abc" is the longest substring without repeats.
Input:  s = "bbbbb"
Output: 1
Explanation: Every substring longer than 1 contains two 'b's.
Input:  s = "pwwkew"
Output: 3
Explanation: "wke" has length 3. "pwke" is not contiguous, so it does not count.

Constraints

  • 0 <= s.length <= 5 * 10^4
  • s consists of English letters, digits, symbols and spaces.

๐Ÿ’ก Key Insight

If a window s[left..right] has no duplicates, every smaller window inside it also has none โ€” so we never need to restart from scratch. Grow the window to the right; when the new character is already inside the window, move left just past its previous occurrence. Each index enters and leaves the window at most once, giving O(n).

Brute Force

TimeO(n ยท m)SpaceO(m)

Intuition

Start a substring at every index i and extend it to the right one character at a time, using a set to detect the first repeat. The moment a repeat appears, no longer substring starting at i can be valid, so stop and move to the next i.

Algorithm

  1. best = 0.
  2. For each start i:
    • Create an empty set seen.
    • For j from i while j < n: if s[j] is in seen, break; otherwise add it and update best = max(best, j - i + 1).
  3. Return best.

Visualization

s = "abcabcbb"

i=0: a b c | a repeats โ†’ length 3
i=1: b c a | b repeats โ†’ length 3
i=2: c a b | c repeats โ†’ length 3
i=3: a b c | b repeats โ†’ length 3
...                       best = 3

Code

java
import java.util.HashSet;
import java.util.Set;

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int best = 0;
        for (int i = 0; i < n; i++) {
            Set<Character> seen = new HashSet<>();
            for (int j = i; j < n; j++) {
                char c = s.charAt(j);
                if (seen.contains(c)) {
                    break; // any longer substring from i also has this repeat
                }
                seen.add(c);
                best = Math.max(best, j - i + 1);
            }
        }
        return best;
    }
}

Complexity

  • Time: O(n ยท m) โ€” for each start we scan at most m characters before a repeat, where m is the alphabet size (โ‰ค 128); O(nยฒ) in general.
  • Space: O(m) โ€” the set holds at most one copy of each character.

Complexity Comparison

Approach Time Space
Brute Force O(nยฒ) O(m)
Sliding Window + HashSet O(n) O(m)
Sliding Window + Last Index O(n) O(m)

Common Pitfalls

  • Moving left backwards: with the last-index map, a character may have been seen before the window started. Always guard with lastIndex[c] >= left (or use left = max(left, last + 1)).
  • Confusing substring with subsequence โ€” the characters must be contiguous.
  • Forgetting the empty string; the loop naturally returns 0, but code that indexes s.charAt(0) up front will crash.
  • Using a 26-slot array: the input includes digits, spaces and symbols, so use 128 (or a map).