力扣的一道中等题目——无重复字符的最长子串
下面是题目链接
要求如下:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
作为一个刷题小白,一开始果然脑紫里面还是蹦出了暴力的想法,但是暴力的方法在这里肯定是要翻跟头的,一旦暴力,需要的时间复杂度极高
所以查看了题解里面的大佬解法,用哈希表的方法结合滑动窗口方式
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
start = 0
max_len = 0
hashmap = {} # 用字典实现哈希表
for end in range(len(s)):
hashmap [s[end]] = hashmap.get(s[end], 0) + 1
# 这是字典的get方法 dic.get(key,default=??) 字典内有这个键值对则取出,没有则取出default指定的值
if len(hashmap) == end - start +1:
# len(dic) 返回的是他有几个键 ,如果 窗口的长度大于 字典键的数量,证明里面有键对应的值大于1
# 即s[end] 与前面的字符串中的某字符一样了
# 这里用的 == 所以证明还没出现重复
max_len = max(max_len, end - start +1)
while end - start + 1 > len(hashmap):
head = s[start]
hashmap[head] -= 1
if hashmap[head] == 0 :
del hashmap[head]
start += 1
return max_len
总体思路上是:
1.初始化窗口
2.窗口的尾部一直向前走,遇到的字符记录到hashmap这个字典中,用“字符 - 出现次数”这样的键值对存储,同时检查 字串中是否有重复字符
3.产生新的合法字串时,其长度与当前已保存的最大长度对比,若大于则替换
检查方法:
if len(hashmap) == end - start +1:
# len(dic) 返回的是他有几个键 ,如果 窗口的长度大于 字典键的数量,证明里面有键对应的值大于1
# 即s[end] 与前面的字符串中的某字符一样了
# 这里用的 == 所以证明还没出现重复
max_len = max(max_len, end - start +1)
while end - start + 1 > len(hashmap):
head = s[start]
hashmap[head] -= 1
if hashmap[head] == 0 :
del hashmap[head]
start += 1
检查思路已经注释
当检查到字串中出现重复,从窗口的第一个元素开始剔除,因为如果重复的元素是第三个,那么第一个元素也作废了,不在计算到当前窗口中合法字串的长度中(遍历过程中窗口中最新合法字串的长度不一定就是最后的结果,最后的结果可能在之前就出现被保存到max_len中了)。
如
abcdc 那么当前窗口中最新的合法字串的长度是2 也就是cd