ntree.aiLongest Substring Without Repeating Characters
Solutions
1. Brute Force
O(n²) time | O(n) space
Intuition
We can take every character and find the longest substring without repeating characters when that character is a start of a substring, keeping the greatest length.
Algorithm
- Create an integer variable
longestwith initial value0. - Iterate through the outer loop from the first character to the last character with
iindex. - For each outer loop iteration, create an empty hash set and iterate through the inner loop from the character at
ito the last character withjindex.- Leave the inner loop if the character at
jis in the hash set. - Otherwise add the character to the hash set and update
longestwithj - i + 1if it is greater.
- Leave the inner loop if the character at
- Return
longest.
p
w
w
k
e
w
012345
ij
p
p is new. length = 1, longest = 1
1 / 16
p
w
w
k
e
w
012345
i
j
p
w
k
e
Code
Code
def lengthOfLongestSubstring(s: str) -> int:
longest = 0
for i in range(len(s)):
seen = set()
for j in range(i, len(s)):
if s[j] in seen:
break
seen.add(s[j])
longest = max(longest, j - i + 1)
return longest/**
* @param {string} s
* @returns {number}
*/
var lengthOfLongestSubstring = function (s) {
let longest = 0
for (let i = 0; i < s.length; i++) {
const seen = new Set()
for (let j = i; j < s.length; j++) {
if (seen.has(s[j])) break
seen.add(s[j])
longest = Math.max(longest, j - i + 1)
}
}
return longest
}import java.util.HashSet;
import java.util.Set;
class Solution {
public int lengthOfLongestSubstring(String s) {
int longest = 0;
for (int i = 0; i < s.length(); i++) {
Set<Character> seen = new HashSet<>();
for (int j = i; j < s.length(); j++) {
if (seen.contains(s.charAt(j))) break;
seen.add(s.charAt(j));
longest = Math.max(longest, j - i + 1);
}
}
return longest;
}
}2. Sliding Window
O(n) time | O(n) space
Intuition
We can keep one substring as a window between the left and right indexes, and extend it by moving right one character forward.
When the character at right is already inside the window, we move left forward until it is gone.
When we move right forward, left never goes back towards the start, because we know that every window that starts before it contains a repeated character.
Then at every right index the window is the longest substring without repeating characters that ends there.
Algorithm
- Create an empty hash set and a
longestinteger variable with initial value0. - Create a
leftindex variable with initial value0. - Iterate through the loop from the first character to the last character with
rightindex.- While the character at
rightis in the hash set, remove the character atleftfrom the hash set and moveleftone step to the right. - Add the character at
rightto the hash set and updatelongestwithright - left + 1if it is greater.
- While the character at
- Return
longest.
p
w
w
k
e
w
012345
leftright
p
p is new. length = 1, longest = 1
1 / 10
p
w
w
k
e
w
012345
left
right
p
w
k
e
Code
Code
def lengthOfLongestSubstring(s: str) -> int:
seen = set()
longest = 0
left = 0
for right in range(len(s)):
while s[right] in seen:
seen.remove(s[left])
left += 1
seen.add(s[right])
longest = max(longest, right - left + 1)
return longest/**
* @param {string} s
* @returns {number}
*/
var lengthOfLongestSubstring = function (s) {
const seen = new Set()
let longest = 0
let left = 0
for (let right = 0; right < s.length; right++) {
while (seen.has(s[right])) {
seen.delete(s[left])
left++
}
seen.add(s[right])
longest = Math.max(longest, right - left + 1)
}
return longest
}import java.util.HashSet;
import java.util.Set;
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> seen = new HashSet<>();
int longest = 0;
int left = 0;
for (int right = 0; right < s.length(); right++) {
while (seen.contains(s.charAt(right))) {
seen.remove(s.charAt(left));
left++;
}
seen.add(s.charAt(right));
longest = Math.max(longest, right - left + 1);
}
return longest;
}
}def lengthOfLongestSubstring(s: str) -> int: pass Press Visualise to step through your code.