滑动窗口高效写法是用双指针+哈希表记录字符最新下标,收缩条件为char in seen and seen[char] >= left,更新left = max(left, seen[char] + 1),扩展无条件进行,时间复杂度O(n)。

滑动窗口怎么写才不超时
Python 里暴力枚举所有子串再逐个判断,时间复杂度是 O(n³),10⁴ 长度的字符串就明显卡顿。真正高效的解法必须用双指针维护一个动态窗口,只遍历一次数组,做到 O(n)。
关键不是“用不用滑动窗口”,而是窗口收缩的条件是否精准——比如求「无重复字符的最长子串」,收缩时机是当 char 在当前窗口中已存在,而不是等窗口长度超标再回头删。
- 用
dict或defaultdict(int)记录字符最新下标,比用set+ 反复.remove()更快也更稳 - 左边界
left更新时别直接赋值,要用max(left, last_seen[char] + 1),防止被更早的重复字符拉回(这是最常踩的坑) - 窗口扩展(右移
right)永远无条件进行;收缩(左移left)只在触发冲突时发生
for right, char in enumerate(s):
if char in seen and seen[char] >= left:
left = seen[char] + 1
seen[char] = right
max_len = max(max_len, right - left + 1)字符串 vs 列表:传入数据类型影响逻辑吗
不影响核心逻辑,但影响索引安全性和边界处理。Python 的 str 和 list 都支持 [i] 和切片,但字符串是不可变对象,某些场景下误用 .append() 会直接报错,而列表不会。
真正要注意的是:如果输入可能是空序列("" 或 []),初始化 left = 0、max_len = 0 就够了,不需要额外判空——因为循环不执行,结果自然为 0。
立即学习“Python免费学习笔记(深入)”;
-
s = ""→enumerate(s)返回空迭代器,循环跳过,max_len保持初值 0 -
s = "a"→ 窗口始终是 [0,0],长度为 1,没问题 - 如果误把字符串当字节序列处理(比如用
s.encode()后又按字符逻辑走),seen键会变成int(ASCII 值),导致逻辑错乱
遇到中文或 emoji 怎么保证正确性
Python 3 中 str 是 Unicode 字符串,一个中文字符、一个 emoji 都算作一个 len() 单位,和英文字符完全等价。只要没手动转成 bytes 或用 ord() 拆解,就无需特殊处理。
但注意:某些字体渲染或终端显示异常(比如 ?? 被当成两个码点)是显示层问题,不影响算法中的 s[i] 索引和 in 判断。
- ✅ 正确:
s = "hello你好?",s[5]是 “你”,len(s)是 11 - ❌ 错误:用
s.encode('utf-8')[i]去取单个“字符”,会按字节截断,导致乱码甚至 IndexError - 如果题目明确要求“按 UTF-8 字节数限制窗口大小”,那才是另一套逻辑,但此时已不属于「连续子串」原意
LeetCode 3 题跑不过?检查这三个地方
LeetCode 第 3 题 “Longest Substring Without Repeating Characters” 是滑动窗口经典题,本地测对但线上 WA 或 TLE,大概率栽在这三处:
- 没更新
seen[char] = right—— 导致重复判断旧位置,窗口收缩失效 - 用
if char in seen:但没加seen[char] >= left条件,把窗口外的历史记录也当作冲突 - 返回值写成
right - left(漏了 +1),长度少算 1
边界 case 如 " "(空格)、"dvdf"、"anviaj" 很容易暴露这些疏漏。调试时打印每步的 left、right、seen,比硬想更快。
滑动窗口真正的复杂点不在结构,而在「收缩时机」和「状态更新顺序」——这两处差一个等号,结果就全错。










