方法一:线性遍历(本质上是双指针)
使用一个变量current
用于保存当前遍历的最长子串,会有两种情况:
- 若当前字符不在
current
中,则将其添加至current
- 若当前字符在
current
中,则先将至此形成的current
的长度与最长子串长度res
作比较,再将current
中原有的这一字符剔除,并将当前字符添加至current
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
res = 0
current = '' # 当前遍历的最长子串
for char in s:
if char not in current:
current += char
else:
res = max(res, len(current))
# 找到重复字符索引,将其剔除
repeat_index = current.find(char)
current = current[repeat_index+1:] + char
res = max(res, len(current))
return res
方法二:动态规划+哈希表
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
dic = {} # 用于储存字符最后出现的索引
res = tmp = 0
for i, c in enumerate(s):
left = dic.get(c, -1)
# dp[j - 1] -> dp[j]
# 重复字符在dp(n-1)之外
if i - left > tmp:
tmp += 1
# 重复字符在dp(n-1)之内
else:
tmp = i - left
res = max(res, tmp) # max(dp[j - 1], dp[j])
# 更新索引
dic[c] = i
return res
方法三:双指针+哈希表
注意这里更新左边界的写法
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
dic = {} # 用于储存字符最后出现的索引
left = -1
res = 0
for i, c in enumerate(s):
if c in dic:
left = max(dic[c], left)
dic[c] = i
res = max(res, i - left)
return res