3. 无重复字符的最长子串
Posted 炫云云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3. 无重复字符的最长子串相关的知识,希望对你有一定的参考价值。
3. 无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: s = "bbbbb"
输出: 1
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
滑动窗口
维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。
- 如果当前遍历到的字符从未出现过,那么直接扩大右边界;
- 如果当前遍历到的字符出现过,则缩小窗口(左指针向右移动),然后继续观察当前遍历到的字符;
- 重复(1)(2),直到左指针无法再移动;
- 维护一个结果
ans
,每次用出现过的窗口大小来更新结果ans
,最后返回ans
获取结果。
关键点
- 用一个 set() 记录出现过的字符
- 用一个滑动窗口记录当前 左指针
l
开始的最大的不重复的字符序列 - 用
ans
去记录目前位置最大的长度,每次滑动窗口更新就去决定是否需要更新ans
以字符串 abcabcbb \\texttt{abcabcbb} abcabcbb 为例,找出从每一个字符开始的,不包含重复字符的最长子串,那么其中最长的那个字符串即为答案。对于示例一中的字符串,我们列举出这些结果,其中括号中表示选中的字符以及最长的字符串:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希集合,记录每个字符是否出现过
occ = set()
n = len(s)
# 右指针,初始值为 0,相当于我们在字符串的左边界,还没有开始移动
r, ans = 0, 0
for l in range(n):
if l != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[l-1])
while r<n and s[r] not in occ:
# 不断地移动右指针
occ.add(s[r])
r += 1
# 第 l 到 r 个字符是一个极长的无重复字符子串
ans = max(ans, r - l + 1)
return ans
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 1 定义维护变量
res, dict = 0, {}
l =0 # 左指针
n = len(s)
for r in range(n):
# 当前位置的元素个数+1
dict[s[r]] =dict.get(s[r],0) +1
# 每个字母都出现一次,不重复,则对结果进行更新
if len(dict) == r-l+1:
res = max(res,r-l+1)
# 当窗口长度大于哈希表长度时候 (说明存在重复元素),窗口不合法
# 缩小窗口,直到不重复
while len(dict) < r-l+1:
dict[s[l]] -=1
if dict[s[l]] ==0:
del dict[s[l]]
l +=1
return res
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 1 定义维护变量
res, dict = 0, {}
l,r =0,0 # 左,右指针
n = len(s)
counter = 0
while r<n:
# 每个字母都出现一次,不重复,则对结果进行更新
if dict.get(s[r],0) >0:
counter += 1 # 重复次数
# 当前位置的元素个数+1
dict[s[r]] =dict.get(s[r],0) +1
# 缩小窗口,直到不重复
while counter>0:
if dict[s[l]]>1:
counter -= 1 # 重复次数
dict[s[l]] -=1
l +=1
res = max(res,r-l+1)
r+=1
return res
'''
用双指针维护一个滑动窗口去裁减字符串子串
建立一个哈希表来跟踪重复字符的最新位置
不断移动右指针,每当遇到一个重复字符c时,在确保左指针不往反方向移动时将其移到c的下一位
移动右指针的过程中,不断维护一个最大长度值并在程序末尾处返回
'''
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 特解
if len(s) <= 1:
return len(s)
# 初始化左指针, 子串最大长度
left, max_len = 0, 0
# 创立哈希表用来跟踪每一个重复字符的位置
# 当右指针碰到了表中的某一个重复字符c, 在确保左指针不往反方向移动时跳到s的下一位
hashtable = {}
# 不断移动右指针
for right in range(len(s)):
# cur_char表示当前字符
cur_char = s[right]
# 如果当前字符之前重复过(重复位置为hashtable[cur_char])
if cur_char in hashtable:
# 在确保左指针不往反方向移动时将左指针移到重复位置 + 1
if hashtable[cur_char] + 1 >= left:
left = hashtable[cur_char] + 1
# 更新当前字符最新重复位置为当前右指针位置
hashtable[cur_char] = right
# 在移动右指针的过程中,不断维护一个最大长度值
max_len = max(max_len, right - left + 1)
# 返回最大长度
return max_len
参考
以上是关于3. 无重复字符的最长子串的主要内容,如果未能解决你的问题,请参考以下文章