题目描述:
给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
解题思路:
1.暴力法
逐个遍历检查s的所有子字符串,判断是否含有重复的字符.
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
res=0
for i in range(len(s)): #i从0到n-1
for j in range(i+1,len(s)+1): #j从i+1到n,双重循环嵌套,枚举出s的所有子字符串.
st=s[i:j]
if self.allUnique(st):
res=max(res,j-i)
return res
def allUnique(self,st): #判断一个字符串中是否有重复字符
l=[]
for ch in st:
if ch not in l:
l.append(ch)
else:
return False
return True
暴力法时间复杂度为O(n^3),最后显示超出时间限制.
2.滑动窗口:
滑动窗口[i,j)可以将两个边界向某一方向滑动,当s[j]不在s[i,j)中时,向右侧滑动索引j;当s[j]在s[i,j)中时,i向右滑动.
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
ls=[]
res,i,j=0,0,0
while i<len(s) and j<len(s):
if s[j] not in ls:
ls.append(s[j])
j+=1
res=max(res,j-i)
else:
ls.remove(s[i])
i+=1
return res
时间复杂度为O(2n)=O(n),最坏情况下,每个字符将被i和j访问两次.
3.优化的滑动窗口:
如果s[j]在[i,j)范围内有重复的字符,不需要逐步增加i.而是直接跳过[i,j]内的所有元素,并将i变为j+1
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
res,i=0,0
d={}
for j in range(len(s)):
if s[j] in d:
i=max(d[s[j]],i)
res=max(res,j-i+1)
d[s[j]]=j+1
return res
时间复杂度为O(n)