Skip to content

Commit cced54f

Browse files
Add 'Longest Substring Without Repeating Characters'
1 parent 0a5ce05 commit cced54f

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ A collection of LeetCode solutions
4040

4141
[Longest Increasing Subsequence](./src/longest_increasing_subsequence.py)
4242

43+
[Longest Substring Without Repeating Characters](./src/test_longest_substring_without_repeating_characters.py)
44+
4345
[Lowest Common Ancestor of a Binary Search Tree](./src/lowest_common_ancestor_of_a_binary_search_tree.py)
4446

4547
[Lowest Common Ancestor of a Binary Tree](./src/lowest_common_ancestor_of_a_binary_tree.py)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
3. Longest Substring Without Repeating Characters
3+
4+
https://leetcode.com/problems/longest-substring-without-repeating-characters
5+
6+
NOTES
7+
* Use a sliding window.
8+
9+
A subarray is a contiguous, non-empty sequence of elements within an array.
10+
Here, we just apply the canonical subarray/substring solution using a sliding
11+
window. Additionally, I've added a slightly more efficient solution that jumps
12+
the left pointer to the index after the last occurrence of the duplicate
13+
character.
14+
"""
15+
16+
from collections import Counter
17+
18+
19+
class Solution:
20+
def lengthOfLongestSubstring(self, s: str) -> int:
21+
left, right, maximum_size = 0, 0, 0
22+
23+
# Maintain a mapping of character -> index of last occurrence.
24+
d: dict[str, int] = {}
25+
26+
while right < len(s):
27+
# Whenever we find a duplicate character, left is updated to the
28+
# index after the last occurrence of that character.
29+
if s[right] in d and d[s[right]] >= left:
30+
left = d[s[right]] + 1
31+
d[s[right]] = right
32+
maximum_size = max(maximum_size, right - left + 1)
33+
right += 1
34+
35+
return maximum_size
36+
37+
38+
class CanonicalSolution:
39+
def lengthOfLongestSubstring(self, s: str) -> int:
40+
left, right, maximum_size = 0, 0, 0
41+
42+
# Maintain a mapping of character -> frequency.
43+
counter: Counter[str] = Counter()
44+
45+
while right < len(s):
46+
counter[s[right]] += 1
47+
# Invariant: left <= right and substring has duplicate.
48+
while left <= right and counter[s[right]] > 1:
49+
counter[s[left]] -= 1
50+
left += 1
51+
maximum_size = max(maximum_size, right - left + 1)
52+
right += 1
53+
54+
return maximum_size
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
3. Longest Substring Without Repeating Characters
3+
4+
https://leetcode.com/problems/longest-substring-without-repeating-characters
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.longest_substring_without_repeating_characters import Solution, CanonicalSolution
10+
11+
12+
class TestSolution(TestCase):
13+
def test_1(self):
14+
exp = 3
15+
assert Solution().lengthOfLongestSubstring("abcabcbb") == exp
16+
17+
def test_2(self):
18+
exp = 1
19+
assert Solution().lengthOfLongestSubstring("bbbbb") == exp
20+
21+
def test_3(self):
22+
exp = 3
23+
assert Solution().lengthOfLongestSubstring("pwwkew") == exp
24+
25+
def test_4(self):
26+
exp = 1
27+
assert Solution().lengthOfLongestSubstring(" ") == exp
28+
29+
def test_5(self):
30+
exp = 2
31+
assert Solution().lengthOfLongestSubstring("abba") == exp
32+
33+
34+
class TestCanonicalSolution(TestCase):
35+
def test_1(self):
36+
exp = 3
37+
assert CanonicalSolution().lengthOfLongestSubstring("abcabcbb") == exp
38+
39+
def test_2(self):
40+
exp = 1
41+
assert CanonicalSolution().lengthOfLongestSubstring("bbbbb") == exp
42+
43+
def test_3(self):
44+
exp = 3
45+
assert CanonicalSolution().lengthOfLongestSubstring("pwwkew") == exp
46+
47+
def test_4(self):
48+
exp = 1
49+
assert CanonicalSolution().lengthOfLongestSubstring(" ") == exp
50+
51+
def test_5(self):
52+
exp = 2
53+
assert CanonicalSolution().lengthOfLongestSubstring("abba") == exp

0 commit comments

Comments
 (0)