Longest Substring Without Repeating Characters (LeetCode)
In this page we will solve the problem Longest Substring Without Repeating Characters from LeetCode.
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.
Constraints:​
0 <= s.length <= 5 * 10^4
s
consists of English letters, digits, symbols and spaces.
Solution for Longest Substring Without Repeating Characters​
Intuition and Approach​
We can solve this problem using the sliding window technique. We will use a hash table to store the characters and their indices. We will also use two pointers, left
and right
, to define the window. The left
pointer will point to the start of the window, and the right
pointer will point to the end of the window.
We will iterate over the string s
using the right
pointer. If the character at the right
pointer is not in the hash table, we will add it to the hash table with its index. We will then calculate the length of the current window by subtracting the left
pointer from the right
pointer and update the maximum length if needed.
If the character at the right
pointer is already in the hash table, we will move the left
pointer to the right of the last occurrence of the character. We will also update the index of the character in the hash table.
We will continue this process until we reach the end of the string s
. The maximum length of the substring without repeating characters will be the answer.
Algorithm​
- Initialize an empty hash table
charIndex
to store the characters and their indices. - Initialize the
left
andright
pointers to 0. - Initialize the
maxLength
variable to store the maximum length of the substring without repeating characters. - Iterate over the string
s
using theright
pointer:- If
s[right]
is not incharIndex
, add it to the hash table with its index. - Calculate the length of the current window and update the
maxLength
if needed. - If
s[right]
is already incharIndex
, move theleft
pointer to the right of the last occurrence ofs[right]
. - Update the index of
s[right]
in the hash table.
- If
- Continue this process until the end of the string
s
. - Return the
maxLength
.
Flowchart​
The flowchart below illustrates the steps involved in the algorithm:
Pseudocode​
function lengthOfLongestSubstring(s: string): number
let charIndex = new Map()
let left = 0
let maxLength = 0
for right from 0 to s.length - 1
if s[right] in charIndex
left = max(left, charIndex[s[right]] + 1)
charIndex[s[right]] = right
maxLength = max(maxLength, right - left + 1)
return maxLength
Implementation and Code​
Here is a live code editor for you to play around with the solution:
function LongestSubstringProblem() { const findLongestSubstring = (s) => { let charIndexMap = {}; let left = 0; let maxLength = 0; for (let right = 0; right < s.length; right++) { if (charIndexMap[s[right]] !== undefined) { left = Math.max(left, charIndexMap[s[right]] + 1); } charIndexMap[s[right]] = right; maxLength = Math.max(maxLength, right - left + 1); } return maxLength; }; const testCases = [ { input: "abcabcbb", expected: 3 }, { input: "bbbbb", expected: 1 }, { input: "pwwkew", expected: 3 }, ]; return ( <div> {testCases.map((testCase, index) => ( <div key={index}> <p> <b>Input:</b> {testCase.input} </p> <p> <b>Output:</b> {findLongestSubstring(testCase.input)} </p> <p> <b>Expected:</b> {testCase.expected} </p> <hr /> </div> ))} </div> ); }
Code in Different Languages​
- JavaScript
- Python3
- Java
- C++
- C
- TypeScript
- Other
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let charIndexMap = {};
let left = 0;
let maxLength = 0;
for (let right = 0; right < s.length; right++) {
if (charIndexMap[s[right]] !== undefined) {
left = Math.max(left, charIndexMap[s[right]] + 1);
}
charIndexMap[s[right]] = right;
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
};
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
char_index_map = {}
left = 0
max_length = 0
for right in range(len(s)):
if s[right] in char_index_map:
left = max(left, char_index_map[s[right]] + 1)
char_index_map[s[right]] = right
max_length = max(max_length, right - left + 1)
return max_length
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charIndexMap = new HashMap<>();
int left = 0;
int maxLength = 0;
for (int right = 0; right < s.length(); right++) {
if (charIndexMap.containsKey(s.charAt(right))) {
left = Math.max(left, charIndexMap.get(s.charAt(right)) + 1);
}
charIndexMap.put(s.charAt(right), right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
}
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> charIndexMap;
int left = 0;
int maxLength = 0;
for (int right = 0; right < s.length(); right++) {
if (charIndexMap.find(s[right]) != charIndexMap.end()) {
left = max(left, charIndexMap[s[right]] + 1);
}
charIndexMap[s[right]] = right;
maxLength = max(maxLength, right - left + 1);
}
return maxLength;
}
};
int lengthOfLongestSubstring(char * s){
int charIndexMap[256];
memset(charIndexMap, -1, sizeof(charIndexMap));
int left = 0;
int maxLength = 0;
for (int right = 0; s[right] != '\0'; right++) {
if (charIndexMap[s[right]] != -1) {
left = fmax(left, charIndexMap[s[right]] + 1);
}
charIndexMap[s[right]] = right;
maxLength = fmax(maxLength, right - left + 1);
}
return maxLength;
}
function lengthOfLongestSubstring(s: string): number {
const charIndexMap: Record<string, number> = {};
let left = 0;
let maxLength = 0;
for (let right = 0; right < s.length; right++) {
if (charIndexMap[s[right]] !== undefined) {
left = Math.max(left, charIndexMap[s[right]] + 1);
}
charIndexMap[s[right]] = right;
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
- Python3
- Java
- C++
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
maxLength = 0
charSet = set()
left = 0
for right in range(n):
if s[right] not in charSet:
charSet.add(s[right])
maxLength = max(maxLength, right - left + 1)
else:
while s[right] in charSet:
charSet.remove(s[left])
left += 1
charSet.add(s[right])
return maxLength
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int maxLength = 0;
Set<Character> charSet = new HashSet<>();
int left = 0;
for (int right = 0; right < n; right++) {
if (!charSet.contains(s.charAt(right))) {
charSet.add(s.charAt(right));
maxLength = Math.max(maxLength, right - left + 1);
} else {
while (charSet.contains(s.charAt(right))) {
charSet.remove(s.charAt(left));
left++;
}
charSet.add(s.charAt(right));
}
}
return maxLength;
}
}
#include <vector>
#include <string>
#include <algorithm>
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.empty()) return 0;
int maxLength = 0;
std::vector<char> seen;
for (char c : s) {
auto it = std::find(seen.begin(), seen.end(), c);
if (it == seen.end()) {
seen.push_back(c);
maxLength = std::max(maxLength, static_cast<int>(seen.size()));
} else {
seen.erase(seen.begin(), it + 1); // Remove characters before the repeated character
seen.push_back(c);
}
}
return maxLength;
}
};
Complexity Analysis​
-
Time Complexity: The time complexity of this solution is , where n is the length of the input string
s
. We iterate over the strings
once using theright
pointer. -
Space Complexity: The space complexity of this solution is , where n is the length of the input string
s
and m is the size of the character set (e.g., 26 for lowercase English letters). We use a hash table to store the characters and their indices, which can have a maximum of m entries.
Test Cases​
We will test the solution with the sample test cases provided in the problem statement.
- Case 1
- Case 2
- Case 3
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
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.