1 题目
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
2 分析
题目要求寻找无重复字符的最长子串,首先无重复字符的最快查找方法是字典或者set,其次计算子串长度的最快方式是终点位置减起始点位置,因此字典记录每个字符的位置是最好的结构。但光有字符位置字典还不够,我们无法记录子串的起始点和终点分别是哪个字符,因此需要两个指针left、right进行记录。
有了以上大致方案,可以写一个循环,当遇到字符不在字典中,则进行记录,右指针右移;当遇到字符在字典中,意味着发生冲突了,需要更新子串长度并将left指针移动到不会重复的位置。这里有个关键点,是不是只要字典中有相同字符,left指针就要移动?其实不是的:例如对s = "abba"而言,当遍历到第二个b的时候,left指针已经移动到位置2了,即使dict'a'=0。那么当遍历到第二个a的时候,即使dict'a'已经存在,但因为dict'a'<left,left是不需要更新的。
3 代码
python
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
# 用两个指针记录子串的起始点和结束点,即可以计算出子串的长度
# 用字典记录每个字符的位置,就可以判断是否有重复
# 当字符已经在字典中出现的时候,如果要将当前字符加入子串中,要求left指针移动到该字符不存在的地方。
pos_dict = {}
left, right = 0,0
longest = 0
for right, char in enumerate(s):
if s[right] in pos_dict:
left = max(left, pos_dict[char]+1)
pos_dict[char] = right
longest = max(longest, right-left+1)
return longest