3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
样例:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
窗口解法(608ms AC)
遍历这个字符串,
第一次:
当搜索到字符
s
k
s_k
sk时,判断
s
0
到
s
k
−
1
s_0到s_{k-1}
s0到sk−1中是否有字符与之重复,若
s
j
s_j
sj重复,定义j为新的下界:
u
n
d
e
r
_
b
o
u
n
d
under\_bound
under_bound,tmp值初始为1,若
s
j
s_j
sj与
s
k
s_k
sk不同,则 tmp+=1 ,若相同,则跳出循环(break),此时最长子串长度为
m
a
x
(
m
a
x
_
l
e
n
g
t
h
,
t
m
p
)
max(max\_length, tmp)
max(max_length,tmp)。
第一次之后:
当搜索到字符
s
k
s_k
sk时,判断
s
u
n
d
e
r
_
b
o
u
n
d
到
s
k
−
1
s_{under\_bound}到s_{k-1}
sunder_bound到sk−1中是否有字符与之重复,若
s
j
s_j
sj重复,定义j为新的下界:
u
n
d
e
r
_
b
o
u
n
d
under\_bound
under_bound, 其余关于tmp的累加和max_length的选择同上。
AC代码如下:
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
max_length = 0
j = 0
under_bound = -1
while j < len(s):
tmp = 1
for k in range(j-1,under_bound,-1):
if k != j and s[k] == s[j]:
under_bound = k
# print(s[k:j+1], under_bound)
break
else:
tmp += 1
j += 1
max_length = max(max_length, tmp)
return max_length
哈希解法(132ms AC)
不得不说字典是降低时间复杂度的治病良方(由于搜寻时间复杂度为
O
(
l
)
O(l)
O(l))
考虑暴力解法:对于每一个字符 s k s_k sk,都寻找以它开头的不重复最长子串,而后找出最长的长度。是具有 O ( n 3 ) O(n^3) O(n3)时间复杂度的解法:遍历整个字符串——遍历从 s k s_k sk开始到发生重复的字符——比较判断字符 s j s_j sj和 s [ k : j ] s[k:j] s[k:j]中每个字符是否重复。
哈希解法的思路:创建一个字典,保留所有无重复字符的索引位置,当发生字符和字典中key重复时,更新索引位置,此时最大长度更新为当前位置和字典中存在的最小位置的距离。
代码如下:
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
#遍历一遍字符串,将没有重复的字母及其位置(如果有重复则保存最后出现的字母)保存至字典
#用一个字典保存各个字母的位置
#最长长度为 i - start + 1
#start = 出现重复字母,旧的 + 1
index = {}
max_len = start = 0
for i in range(len(s)):
if s[i] in index:
start = max(start,index[s[i]] + 1)
#print(start,end="")
index[s[i]] = i
max_len = max(max_len , i - start + 1)
return max_len