2

I'm trying to improve my Python by solving some problems on LeetCode.

I'm currently working on the Longest Substring Without Repeating Characters problem:

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3. 
             Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

I am trying to do brute forcing, by finding all substrings and then finding the longest one:

def lengthOfLongestSubstring(self, s: str) -> int:
        list_of_values = [0]
        if (not s):
            return 0

        new_list = list(s[0])
        i = 1
        size_s = len(s)
        while i < size_s:
            if s[i] not in new_list:
                new_list.append(s[i])
                i += 1
            else:
                list_of_values.append(len(new_list))
                new_list = []
                s = s[1:]
                i = 0
                size_s = len(s)
                if size_s < max(list_of_values):
                    break
        return max(max(list_of_values), len(new_list))

The solution works, but it times out for the last test case on LeetCode (a very long string). Does anyone have suggestions on how to make this faster?

Enlico
  • 23,259
  • 6
  • 48
  • 102
Paolo
  • 21,270
  • 6
  • 38
  • 69
  • "I am trying to do brute forcing, by finding all substrings" Yes, this is the problem. You need to think of a way to do this more efficiently. Also, even in your solution you aren't applying the right data structures; consider the guarantees you need out of `new_list` - you are just adding things to it, taking its size, and testing for membership. A set is a better choice, to improve your membership test. – GManNickG May 16 '20 at 16:38
  • 2
    think of two pointers. Fix first pointer. Move second pointer until you see a repetition ( can be done using a Set/Map ). Then move first pointer until duplicates are removed. Update the max length ( length between first and second pointers). Do it until right pointer reaches the end. – SomeDude May 16 '20 at 16:42
  • have you looked at the discussion section of that Leetcode problem yet? For most problems they typically have a few good solutions. – Kurt Kline May 16 '20 at 16:43
  • Also, copying the whole list without its first item and building again the substring you already had each time you find a duplicate char is very inefficient. Just keep two indices to track the start and end of your current longuest possible substring, and as already suggested, use a set to keep the values it contains. This will run in O(n) instead of O(n**2). – Thierry Lathuille May 16 '20 at 16:46
  • Ops, I have suggested what @SomeDude suggested already. Sorry, it was not intentional. – Enlico May 16 '20 at 16:51

3 Answers3

4

These are just some hints for the algorithm.

You can set two "pointers" to the first letter,

abcabcbb
^start
^end

then you advance the end pointer and put the letters in a hashmap or somthing, so you can efficiently check for repeated letters when you advance. As soon as you get a repetition,

abcabcbb
^start
   ^end

you save the two positions and the length in list or tuple, and then you advance start until there are no more repeated letters

abcabcbb
 ^start
   ^end

Then you start advancing end again, repeating the process, by overriding the two saved positions and the length only if the lenght increases.

You should end up with the start and end positions of the last longest substring you met, in this case bcb

abcabcbb
    ^start
      ^end

Note that it is the last, and other valid candidates are abc, bca, and so on.

Paolo
  • 21,270
  • 6
  • 38
  • 69
Enlico
  • 23,259
  • 6
  • 48
  • 102
1

You can do this in 2 steps:

Step 1. Generate all possible combinations of substrings

Step 2. Use set() to weed out strings with repeated letters

st ="pwwkew"
n=len(st)
# step 1
li = [st[i:j] for i in range(n) for j in range(i+1, n+1)]
# step 2
max_len =max([len(el) for el in li if len(el) == len(set(el))])

print(max_len)
LevB
  • 925
  • 6
  • 10
0

Visit https://www.youtube.com/watch?v=FWg4HZlAVcc for explanation. It is faster than 99.97% of python solution

      class Solution:
            def lengthOfLongestSubstring(self, s: str) -> int:
            ss = ''
            cnt = 0
            for ch in s:
                if ch in ss:
                    if len(ss) > cnt:
                        cnt = len(ss)
                    ss = ss[ss.index(ch)+1:]
            
                ss+=ch
            if len(ss) > cnt:
                cnt = len(ss)
            return cnt**strong text**