题目描述:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
解法:
完整代码:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
start = -1
max = 0
d = {}
for i in range(len(s)):
if s[i] in d and d[s[i]] > start:
start = d[s[i]]
d[s[i]] = i
else:
d[s[i]] = i
if i - start > max:
max = i - start
return max
思路讲解:
首先,对于这种求子串长度问题,我们要定义计算长度的起始位置--start, 其次是遍历字符串筛选不重复的字符时,表示当前判断的字符位置的变量i,以及我们要使用的哈希表,字典d
1.首先我们要考虑字符串s为空的情况,此时字符串的长度为0,而要求的输出是1.我们在计算最长子串长度时用的是i-start,因此当i只能为0时,start的初始赋值一定是-1方可满足这一特殊情况
2.紧接着遍历我们传入函数的字符串s,并判断每次遍历的时候,这个字符是否存在于我们创建的字典中,如果存在,并且这个字符的位置还在start右边
(是否会出现在start左边的情况呢,会的:d[s[i]]
会出现在 start
左边的情况,发生在我们更新 start
之后,且当前字符在 start
之前的子串中出现过。这种情况实际上意味着这个字符已经不再影响当前无重复子串的长度计算)
此时,咱们就把这个字符给加到字典中,序号就是该字符在字符串中的序号i,d = {(s[i], i)}
同理如果不在我们的字典里呢,我们就把它加进去,序号同样是该字符在字符串中的序号i,
d = {...(s[i], i)...}.此时再做判断,看看这个i减去start得到的长度max和上一次得到的max进行比较,哪个大max就是哪个.
3.最后返回max即可
示例
假设字符串 s = "abcabcbb"
,执行过程如下:
i = 0, s[0] = 'a'
:d = {'a': 0}
,max = 1
i = 1, s[1] = 'b'
:d = {'a': 0, 'b': 1}
,max = 2
i = 2, s[2] = 'c'
:d = {'a': 0, 'b': 1, 'c': 2}
,max = 3
i = 3, s[3] = 'a'
:start = 0
,d = {'a': 3, 'b': 1, 'c': 2}
,max = 3
i = 4, s[4] = 'b'
:start = 1
,d = {'a': 3, 'b': 4, 'c': 2}
,max = 3
i = 5, s[5] = 'c'
:start = 2
,d = {'a': 3, 'b': 4, 'c': 5}
,max = 3
i = 6, s[6] = 'b'
:start = 4
,d = {'a': 3, 'b': 6, 'c': 5}
,max = 3
i = 7, s[7] = 'b'
:start = 6
,d = {'a': 3, 'b': 7, 'c': 5}
,max = 3
最终,返回的 max
为 3,对应子串 "abc"
。