Longest Substring Without Repeating Characters medium
Problem Statement
Given a string s
, find the length of the longest substring without repeating characters.
Example 1:
Input: s = "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: s = "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1.
Example 3:
Input: s = "pwwkew" Output: 3 Explanation: The answer is "wke", with the length of 3. Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
Steps
The problem can be efficiently solved using a sliding window approach with a dictionary (or hashmap) to track the last seen index of each character.
-
Initialization: Create a dictionary
charIndex
to store the last seen index of each character. Initialize amaxLength
variable to 0, representing the length of the longest substring found so far. Initializestart
andend
pointers to 0, defining the sliding window's boundaries. -
Sliding Window: Iterate through the string using the
end
pointer. For each character:- Check if the character is already present in
charIndex
and if its last seen index is within the current window (charIndex[s[end]] >= start
). - If it is, it means we've encountered a repeating character. Move the
start
pointer to one position after the previous occurrence of the repeating character (start = charIndex[s[end]] + 1
). This shrinks the window to eliminate the repetition. - Update the last seen index of the current character in
charIndex
. - Update
maxLength
to the maximum ofmaxLength
and the current window size (end - start + 1
).
- Check if the character is already present in
-
Return: After iterating through the entire string, return
maxLength
.
Explanation
The sliding window technique efficiently explores all possible substrings. The dictionary allows for quick lookups of character indices, making the check for repeating characters O(1) on average. Moving the start
pointer only when necessary ensures that we don't unnecessarily shrink the window. The algorithm maintains the invariant that the window always contains a substring without repeating characters.
Code
public class Solution {
public int LengthOfLongestSubstring(string s) {
Dictionary<char, int> charIndex = new Dictionary<char, int>();
int maxLength = 0;
int start = 0;
int end = 0;
while (end < s.Length) {
if (charIndex.ContainsKey(s[end]) && charIndex[s[end]] >= start) {
start = charIndex[s[end]] + 1;
}
charIndex[s[end]] = end;
maxLength = Math.Max(maxLength, end - start + 1);
end++;
}
return maxLength;
}
}
Complexity
- Time Complexity: O(n), where n is the length of the string. In the worst case, we iterate through the string once.
- Space Complexity: O(min(m, n)), where n is the length of the string and m is the size of the character set. In the worst case, the dictionary may store up to min(m,n) entries. If the string contains all unique characters, the space complexity will be O(n). If the string has a small character set (e.g., only lowercase English letters), the space complexity will be O(m) where m is the size of the character set (26 in this case).