LeetCode Longest Substring Without Repetition Solution in Python | Towards Data Science

LeetCode is a platform that gives access to numerous coding problems that are usually asked in technical interviews of tech giants such as Google, Meta and Amazon for Engineering and Machine Learning positions.
In today’s article, we are going to explore a couple of approaches for the third problem on LeetCode problem which is of medium difficulty level and is called “Longest substring without repetition”.
Given a string s, find the length of the longest substring without repeating characters.
Example 1:
Input: s = "abcabcbb"Output: 3Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: s = "bbbbb"Output: 1Explanation: The answer is "b", with the length of 1.
Example 3:
Input: s = "pwwkew"Output: 3Explanation: 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.
Example 4:
Input: s = ""Output: 0
Constraints:
0 <= s.length <= 5 * 104
s consists of English letters, digits, symbols and spaces.
Source: LeetCode
The most intuitive approach to the problem would be to perform a brute force search by using two nested loops.
class Solution:    def lengthOfLongestSubstring(self, s: str) -> int:                longest_str = ""        for i, c in enumerate(s):            canditate_str = str(c)            for j in range(i + 1, len(s)):                if s[j] not in canditate_str:                    canditate_str += str(s[j])                else:                    break            if len(canditate_str) > len(longest_str):                longest_str = canditate_str            if len(s) - i <= len(longest_str):                break           return len(longest_str)
Even though the above algorithm would solve the problem in question, the time complexity — which in this case is O(n2) — is an issue as we can definitely do better than this.
Now in order to improve the previous answer, we need to somehow make a single pass over the string containing the characters. One approach that could help us do so is the so called sliding window.
To make clear what I mean with sliding window, let’s consider the following string below (at the top we show the index of each individual character):
#               0 1 2 3 4 5 6 7   #               a b c a b c b b
A sliding window has a starting and ending indices:
#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start         |# end           |
Depending on the algorithm, the starting and ending indices will move accordingly. In our case, we would want the sliding window to be created and move forward as illustrated below.
#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start         |# end             |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start         |# end               |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start         |# end                 |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start           |# end                 |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start           |# end                   |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start             |# end                   |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start             |# end                     |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start               |# end                     |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start               |# end                       |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start                   |# end                       |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start                   |# end                         |#               0 1 2 3 4 5 6 7   #               a b c a b c b b# start                       |# end                         |
An algorithm that can reflect the logic described in the diagram/code below is shown below. We use a Hash Map (i.e. a Python dictionary) where keys correspond to characters seen so far, and values to the index this particular character was last seen.
class Solution:    def lengthOfLongestSubstring(self, s: str) -> int:        chars = {}        start = 0        max_length = 0                    for end, c in enumerate(s):            if c in chars:                start = max(start, chars[c] + 1)                        max_length = max(max_length, end - start + 1)            chars[c] = end        return max_length
Now in terms of complexity, we made a significant improvement compared to the brute force approach since now we iterate over the string only once and thus the time complexity of our solution is O(n).
In today’s article we walked through a couple of potential solutions to the third problem on LeetCode platform called “Longest substring without repetition”.
We initially created a less optimal solution that involves brute force by creating two nested loops in order to identify which substring in the input string is the longest one.
Finally, we optimised the algorithm by using sliding windows and hash maps (i.e. Python dictionaries) so that we will need to made just a single pass over the string and solve the problem in O(n) time.
Become a member and read every story on Medium. Your membership fee directly supports me and other writers you read. You’ll also get full access to every story on Medium.
gmyrianthous.medium.com
You may also like