3. 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
代码1(滑动窗口,集合):
左右两个指针控制窗口的长度。
右指针元素不在集合中时添加该元素,右指针右移;右指针元素在集合中时,移除最左边元素,左指针右移,如果元素还在集合中,再移除最左边元素,直到元素不在集合中。
于是我们就可以得到窗长right-left。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
if n == 0:
return 0
elif n == 1:
return 1
left = right = 0
ans = 0
hash_set = set()
while right < n:
if s[right] in hash_set:
hash_set.remove(s[left])
left += 1
else:
hash_set.add(s[right])
right += 1
ans = max(ans, right-left)
return ans
代码2(哈希表/字典):
思路与代码1类似,只是left指针不是+1,而是直接赋值重复元素序号+1。
但是此处有个问题,就是left前面的元素并不是删除了,因此如果后面出现与left前面重复的元素,会导致长度计算错误,直接算两个相距最远的重复元素之间的长度了。
比如‘abba’,直接赋值的话输出会是a和a之间的长度3,而不是正确答案2。
所以我们需要在赋值前与原left比较取最大数,或者修改判断条件为
if s[right] in hash_map and hash_map[s[right]] >= left:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
if n == 0:
return 0
elif n == 1:
return 1
left = right = 0
ans = 0
hash_map = {}
while right < n:
if s[right] in hash_map:
left = max(left, hash_map[s[right]]+1)
hash_map[s[right]] = right
else:
hash_map[s[right]] = right
right += 1
ans = max(ans, right-left)
return ans
附两篇大佬介绍哈希表的博文: