Solution: Longest Substring without Repeating Characters
Let's solve the Longest Substring without Repeating Characters problem using the Sliding Window pattern.
Statement
Given a string, str
, return the length of the longest substring without repeating characters.
Constraints:
-
str.length
str
consists of English letters, digits, symbols, and spaces.
Solution
So far, you’ve probably brainstormed some approaches on how to solve this problem. Let’s explore some of these approaches and figure out which one to follow while considering time complexity and any implementation constraints.
Naive approach
The naive approach is to explore all possible substrings. For each substring, we check whether any character in it is repeated. After checking all the possible substrings, the substring with the longest length that satisfies the specified condition is returned.
The total time complexity of this solution is . To explore all possible substrings, the time complexity is , and to check whether all the characters in a substring are unique or not, the time complexity can be approximated to . So, the total time complexity is . The space complexity of this naive approach is , where is the size of the character set and is the size of the string.
Optimized approach using sliding window
We use a modified version of the classic sliding window method. Instead of a fixed-size window, we allow our window to grow, looking for the window that corresponds to the longest substring without repeating characters.
We initialize an empty hash map along with a variable to track character indices and the starting point of the window. Next, we traverse the string character by character. During each iteration, the current character is checked to see if it exists in the hash map. If it does not exist, it is added to the hash map along with its index. However, if the current character already exists in the hash map and its index falls within the current window, it indicates that a repeating character has been discovered. In this case, the start of the window is updated to the previous location of the current element and incremented, and the length of the current window is calculated. The longest substring seen so far is updated if the length of the current window is greater than its current value. Finally, the length of the longest substring is returned as the result.
Here’s how we implement this technique.
-
We initialize the following set of variables to
0
to keep track of the visited elements.-
windowStart
: The starting index of the current substring. -
windowLength
: The length of the current substring. -
longest
: The length of the longest substring.
-
-
For every element in the string, we check whether or not it’s present in the hash map.
- If it isn’t present, we store it in the hash map such that the key is the current element and the value is its index in the string.
-
If it’s already present in the hash map, then the element may have already appeared in the current substring. For this, we check if the previous occurrence of the element is before or after the starting index,
windowStart
, of the current substring.-
If it’s after
windowStart
, we calculate the current substring’s length,windowLength
, as the difference between the current index andwindowStart
. Iflongest
is less than the newwindowLength
, we setlongest
aswindowLength
. -
To prevent the repetition of the current element in the current window, the next candidate substring will be set to start from just after the last occurrence of the current element.
-
- We then update the value of the corresponding key in the hash map, setting it to the index of the current element.
-
After traversing the entire sequence of elements,
longest
holds the length of the longest substring without repeating characters.
The following illustration shows these steps in detail: