打败算法 —— 无重复字符的最长子串
本文参考
出自LeetCode上的题库 —— 无重复字符的最长子串,本题又是滑动窗口的一次应用
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
无重复字符的最长字串问题
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度
返回滑动窗口每次移动后,窗口中的最大值
示例1:
输入:s = "abcabcbb"
输出:3
解释:因为无重复字符的最长子串是 "abc",所以其长度为 3
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是"wke",所以其长度为 3
解题思路
之前做到过和本题类似的题目"最小覆盖字串"(https://www.cnblogs.com/kuluo/p/15945437.html),仍然按照滑动窗口的基本思路,当窗口内的子字符串始终满足"不重复"的要求时,右指针一直向右移动,直到窗口内的子字符串出现重复字符
在"最小覆盖字串"中,我们就已经发现,如果左指针每次只移动一个距离,会浪费很多的循环,我们让左指针直接跳转到特定位置,满足窗口内的要求。在本题中,可以让左指针直接移动到重复字符第一次出现时的下一个位置上
滑动窗口解法
class Solution:
def length_of_longest_substring(self, s: str) -> int:
left = 0
right = 1
ans = 0
while right <= len(s):
sub_str = s[left:right]
# 判断窗口中是否有重复字符
step = self.step(sub_str)
if step:
left += step
else:
ans = ans if ans >= len(sub_str) else len(sub_str)
right += 1
return ans
def step(self, s: str) -> int:
# 记录子串中各个字符出现的位置
rel = dict()
for i in range(len(s)):
c = s[i]
if c in rel.keys():
# 返回需要让左指针跳转的步长
return rel[c] + 1
else:
rel[c] = i
return 0