剑指 Offer 48. 最长不含重复字符的子字符串
一、题目
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:s.length <= 40000
二、答案
2.1 解题思路
双指针法:
- 用start作为不重复子串的头指针,用end代表不重复子串的尾指针(用循环是,尾指针可以直接用当前循环的index来表示)
- 如果遍历的元素重复,则更新hash_table的键值对中对应的index值
- 每次循环只要元素不重复,都要加入到hash_table中
- 然后结果长度result = max(result, end-start+1)
2.2 例子示例
以 “dvdlf” 为例,初始化,start指针指向第0个元素,end指针指向1, hash_talbe中已经放了一个元素即{d:0}
-
初始化start, end, hash_table, result = 0,0, {s[0]:0}, 1
-
此时默认有一个元素了,所以初始长度result=1
id 0 1 2 3 4 s d v d l f 指针 start = 0,end = 0 hash_table {d:0} result 初始:result = 1
-
第一次迭代
- end指针右移一格, 将end所指向的值加入hash_table
- result = max(result, end-start+1)
id 0 1 2 3 4 s d v d l f 指针 start = 0 end = 1 hash_table {d:0} {d:0,v:1} result 初始:result = 1 result = max(1, 1-0+1)=2 -
迭代二次
-
end指针右移一格,,然后发现此时的end指针所指向的值重复
-
移动start指针到重复元素的后一个元素,注意比较移到重复后一个元素的id与当前的id的大小,取大的那个
start = max(start, hash_table[s[2]+1) # max(0, 1) = 1
-
更新hash_table中重复键值对的值,那么d:0 变为 d:2
id 0 1 2 3 4 s d v d l f 指针 start = 1 end = 2 hash_table {d:0} {d:0, v:1} {d:2, v:1} result 1 2 result = max(2, 2-1+1)=2 -
-
迭代第三次
- end指针右移一格, 将新的键值对加入hash_table
- result = max(result, end-start+1)
id 0 1 2 3 4 s d v d l f 指针 start = 1 end = 3 hash_table {d:0} {d:0, v:1} {d:2, v:1} {d:2, v:1, l:3} result 1 2 2 result = max(2, 3-1+1)=3 -
迭代第四次
- end指针右移一格, 将新的键值对加入hash_table
- result = max(result, end-start+1)
id 0 1 2 3 4 s d v d l f 指针 start = 1 end = 4 hash_table {d:0} {d:0, v:1} {d:2, v:1} {d:2, v:1, l:3} {d:2, v:1, l:3, f:4} result 1 2 2 3 result = max(3, 4-1+1) = 4 -
循环结束,返回结果result = 4
2.3 代码
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 双指针法
# start, end 分别指向不重复子串的首位序号
# hash_table用来存访问过的键值对
# result来表示最长不重复字符串的长度
# 初始化
# start, end, hash_table, result = 0, 1, {s[0]:0}, 1
# 这样的初始化默认字符串大于0,所以要进行空字符串的判断
if len(s)==0: return 0
start, hash_table, result = 0, {s[0]:0}, 1
# 直接将end设置为迭代的index
for end in range(1, len(s)):
if s[end] in hash_table:
start = max(start, hash_table[s[end]]+1)
hash_table[s[end]] = end
result = max(result, end-start+1)
return result