Leetcode: 3. Longest Substring Without Repeating Characters

Problem Statement: Find the length of the longest substring without repeating characters in \(s\).

Be \(s_0, s_1, s_2, ..., s_{n-1}\) the characters in \(s\) and \(s_i, s_{i+1}, ..., s_{k}\) one substring without repeating characters in \(s\). If \(s_{k+1}\) is not a character in \(s[i..k]\), then we can append \(s_{k+1}\) to the substring and make it longest. If \(s_{k+1}\) is a character already in \(s[i..k]\), then appending \(s_{k+1}\) would make the substring invalid. Thus, the best we can do is to continue searching if the longest substring starts on \(s_{j+1}\) for \(i\leq j\) and \(s_j=s_{k+1}\). To summarize, we want to apply Sliding Window technique to go over \(s\) expanding and contracting the longest substring until that point. The following code uses a Deque to keep the string and a Set to quickly check if a given character was seen before.

With \(n=|s|\), we have

from collections import deque


def solve(s):
    seen = set()
    match = deque()
    ans = 0
    for sym in s:
        if sym in seen:
            while len(match) > 0 and match[0] != sym:
                seen.remove(match.popleft())
            match.popleft()
        seen.add(sym)
        match.append(sym)
        ans = max(ans, len(match))

    return ans


assert solve("abcabcbb") == 3
assert solve("bbbbb") == 1
assert solve("pwwkew") == 3
assert solve("tmmzuxt") == 5


class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        return solve(s)