无重复字符的最长子串
题目描述:
解题思路:
python3
- 第一种:这个方法也是很无脑,暴力法解决,所以运行速度就很慢。我的想法就是从头开始一点一点遍历,找到所有可能,然后把每次的长度都存进数组
Sum
,中,最后就求这个Sum
中的最大元素。运行速度也是特别的慢,所以需要改进方法。 - 时间复杂度:O(N^2)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 1:
return 1
Sum = []
for i in range(len(s)-1):
large = [s[i]]
for j in range(i+1, len(s)):
Sum.append(len(large))
if s[j] in large:
break
else:
large.append(s[j])
Sum.append(len(large))
maxi = max(Sum, default=0)
return maxi
- 第二种:这里我们为了降低时间复杂度,我们用到这个方法。这个方法的思路就是,从头开始遍历字符串,然后定义一个
set
集合p
和一个temp
来保存p
中的字符数量,然后遍历第一个元素,将这个元素放入p
中,然后判断下一个元素是否在集合p
中,如果在,说明不是无重复字符的子串,则将这个之前的重复元素,包括这个重复元素在内的前面的所有元素用remove
移除,因为要形成连续子串,然后每移除一个字符,temp
就相应减去1,最后让temp
和原先定义的large
作比较,这样是为了排除s
为空的情况,最后将temp
赋给large
,最后返回所求无重复的最长子串数目large
。 - 时间复杂度:O(N)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
a = 0
large = 0
p = set()
temp = 0
for i in range(len(s)):
temp += 1
while s[i] in p:
p.remove(s[a])
a += 1
temp -= 1
if temp > large:
large = temp
p.add(s[i])
return large
或者,用字典来储存元素,然后用temp
来表示,如果不满足条件就加一,然后相应所求最大子串的数量就减一。思路都是一样的,都是滑动窗口法。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
p = {}
temp = 0
large = 0
for i in range(len(s)):
if s[i] in p and temp <= p[s[i]]:
temp = p[s[i]] + 1
large = max(i-temp+1, large)
p[s[i]] = i
return large
- 第三种:最后介绍一个运行超级快的方法,我理解了这个方法的思路,但是不太明白为什么会比上面的方法快那么多…,这里大概讲讲吧。其实也还是那个思路,就是从头开始遍历,每个字符也都是存在字典中,然后遍历过程中,如果当前元素不在这个字典中,则
large = i - temp
,其实也就是加一,因为每遍历一次i
也会加一,这样的话large
就可以保存这个无重复字符最长子串的数量了。如果后面遇到出现重复的字符,那么令temp = p[s[i]]
,这一步直接把起点拉到原重复元素temp
位置,从这个位置开始重新计算最大子串。【这里要注意一个细节地方,我在一开始写的时候出现了一个错误。就是我直接把这个重复元素先放入,然后从这个新重复元素往后开始找新的子串,这个是错误的!!就比如说“dvdf”
,如果按照这个错误做法,找到重复元素d
之后从第二个重复元素往后找,最后返回的就不是正确答案3
,而是2
,所以这里我们不能先放入重复元素,要先从之前的那个重复元素的后面开始找新的子串,这样才是对的。】最后算得的large
就是所求的无重复最长子串的长度了。 - 时间复杂度:O(N)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
temp = -1
p = {}
large = 0
for i in range(len(s)):
if s[i] in p and temp < p[s[i]]:
temp = p[s[i]]
else:
if i - temp > large:
large = i - temp
p[s[i]] = i
return large