算法3. 无重复字符的最长子串
给定一个字符串
s
,请你找出其中不含有重复字符的 最长 子串 的长度。示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。
class Solution:def lengthOfLongestSubstring(self, s: str) -> int:ans = left = 0cnt = defaultdict(int) # 维护从下标 left 到下标 right 的字符及其出现次数for right, c in enumerate(s):cnt[c] += 1while cnt[c] > 1: # 窗口内有重复字母cnt[s[left]] -= 1 # 移除窗口左端点字母,直到剔除重复字母(cnt[c]==1)left += 1 # 缩小窗口ans = max(ans, right - left + 1) # 更新窗口长度最大值return ans
✅ 解法使用了「滑动窗口 + 双指针」
1. 双指针(Two Pointers)
- 使用了两个指针:
left
:指向当前窗口的左边界。right
:通过for right, c in enumerate(s)
遍历字符串,作为右指针。
- 两个指针共同维护一个动态变化的子串区间
[left, right]
。
2. 滑动窗口(Sliding Window)
- 窗口
[left, right]
表示当前考察的子串。 - 每次
right
向右移动一位,加入一个新字符c
。 - 如果加入后导致字符重复(
cnt[c] > 1
),就不断移动left
指针,缩小窗口,直到重复字符被移出,恢复“无重复”状态。 - 这样窗口始终维持一个不含重复字符的合法子串,并不断尝试扩展和滑动。
3. 哈希表辅助判断重复
cnt = defaultdict(int)
用来统计当前窗口中每个字符的出现次数。- 用于快速判断是否出现重复字符。
4. 更新答案
- 每当窗口合法时(即无重复),用
right - left + 1
更新最大长度。