题目:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是 3。
给定 "bbbbb" ,最长的子串就是 "b" ,长度是 1。
给定 "pwwkew" ,最长子串是 "wke" ,长度是 3。请注意,你的答案必须是一个子串,"pwke" 是子序列不是子串。
解法思路:
首先想到的是暴力解法,在所有的子串中找出不含重复字符的,再求最长,可以用两个嵌套for循环来实现,但这种方式时间复杂度较高。
可以使用“滑动窗口”的方式,若窗口下一个字符与窗口子串中的字符不重复,则将其包含进去,窗口右界向右拓展1个长度。若若窗口下一个字符已经出现在窗口子串中,则重置窗口的左界位置到重复字符在窗口子串中所在位置的后一位。
我的解法:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if s == '': #判断空串
return 0
p = 0 #窗口左界
q = 1 #窗口右界
max_len = 1 #不重复子串的最大长度
while q<len(s):
if s[q] in s[p:q]: #判断窗口的下一个字符是否已在窗口内出现
p += s[p:q].index(s[q])+1 #更新窗口左界
q += 1 #更新窗口右界
else:
q += 1 #更新窗口右界,无需更新左界
if max_len< q - p:
max_len = q - p #更新最大长度
return max_len
官方解法:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希集合,记录每个字符是否出现过
occ = set()
n = len(s)
# 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans = -1, 0
for i in range(n):
if i != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[i - 1])
while rk + 1 < n and s[rk + 1] not in occ:
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans