news 2026/8/25 7:06:15

高频必考!无重复最长子串:滑动窗口为什么是 O(n) 而非 O(n²)?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
高频必考!无重复最长子串:滑动窗口为什么是 O(n) 而非 O(n²)?

LeetCode 3「无重复字符的最长子串」,「国内大厂面试命中率 TOP 5」
但很多人写出来的代码要么超时,要么边界错,要么自己都说不清为什么能 O(n)。

今天我不只给你“能 AC 的代码”,更给你一套「“同向双指针 + 哈希表定位”」的通用框架。以后遇到“子串”类问题,你都能用同样的套路——「右扩左缩,窗口内保持合法状态」


📦 题目速览(30 秒读懂)

给定字符串s,找出「不含有重复字符」「最长子串」的长度。

「示例:」

输入: "abcabcbb" → 输出 3(子串 "abc") 输入: "bbbbb" → 输出 1(子串 "b") 输入: "pwwkew" → 输出 3(子串 "wke",注意不是 "pwke" 因为它不连续)

「约束:」长度0~5×10⁴,字符集很大(字母+数字+符号+空格)—— 暴力法必挂。


🧠 核心思路:从“三层循环”到“一次遍历”

暴力在哪儿?

foriinrange(n):
forjinrange(i, n):
if子串 s[i:j+1] 无重复:
更新最大长度

O(n³),n=50000 时直接爆炸。

如何优化?——复用已有信息

「关键观察:」
如果当前窗口[left, right]内无重复,那么当right右移一位时,「只需要检查新字符是否在窗口内出现过」

  • 若没出现过 → 窗口直接扩展,长度 +1
  • 若出现过 → 不必回退right,只需「将left跳到重复字符的下一个位置」,窗口依然合法。

这就是滑动窗口的精髓:「两个指针都只向前移动」,每个字符最多被访问两次(一次进窗口,一次出窗口),所以总时间 O(n)。


🖼️ 图解全过程(手把手走一遍)

s = "abcabcbb"为例:

步骤右指针 R当前字符窗口内容左指针 L是否重复?动作最大长度
10a{a}0扩展窗口1
21b{a,b}0扩展窗口2
32c{a,b,c}0扩展窗口3
43a{a,b,c,「a」}0✅ a 重复L 跳到 0+1=13
54b{b,c,a,「b」}1✅ b 重复L 跳到 1+1=23
65c{c,a,b,「c」}2✅ c 重复L 跳到 2+1=33
76b{a,b,c,「b」}3✅ b 重复L 跳到 4+1=53
87b{c,b,「b」}5✅ b 重复L 跳到 6+1=73

最终最大长度为「3」(窗口为 "abc" 或 "bca" 等),正确 ✅

注意观察:right从未回退,left也只向右跳跃,两指针总移动次数 ≤ 2n。


💻 代码实现(Python + Java)

Python 版(推荐写法)

classSolution:
deflengthOfLongestSubstring(self, s: str)-> int:
last_pos = {}# 字符 → 最近一次出现的下标
left =0
max_len =0

forright, chinenumerate(s):
# 如果 ch 已经在当前窗口内(last_pos[ch] >= left)
ifchinlast_posandlast_pos[ch] >= left:
left = last_pos[ch] +1# 直接跳到重复字符的下一位

last_pos[ch] = right# 更新最新位置
max_len = max(max_len, right - left +1)

returnmax_len

Java 版

classSolution{
publicintlengthOfLongestSubstring(String s){
Map<Character, Integer> lastPos =newHashMap<>();
intleft =0, maxLen =0;

for(intright =0; right < s.length(); right++) {
charch = s.charAt(right);
if(lastPos.containsKey(ch) && lastPos.get(ch) >= left) {
left = lastPos.get(ch) +1;
}
lastPos.put(ch, right);
maxLen = Math.max(maxLen, right - left +1);
}
returnmaxLen;
}
}

⚠️「致命坑」:判断重复时「必须」加上>= left,因为字符可能早在left左边出现过,但早已被排除在窗口外,此时不该收缩左指针。

漏掉这个条件,代码会出错(比如"tmmzuxt"会返回错误长度)。


⏱️ 复杂度分析(面试必问)

  • 「时间复杂度:O(n)」
    右指针遍历一次 O(n),左指针最多也移动 n 次(只增不减),哈希表操作 O(1),总计 O(n)。

  • 「空间复杂度:O(min(m, n))」
    m 为字符集大小(如 ASCII 128,Unicode 很大)。当字符集有限时(如小写字母 26 个),可视为「O(1)」额外空间。


🚀 举一反三:4 道高频变种题,一套框架通吃

题目差异点应对策略
「LeetCode 209. 长度最小的子数组」求和 ≥ target 的最短连续子数组窗口内维护元素和,右扩,满足条件时收缩左边界并更新最小长度
「LeetCode 904. 水果成篮」最多包含 2 种字符的最长子串哈希表计数,种类 > 2 时 left 右移直到种类 ≤ 2
「LeetCode 76. 最小覆盖子串」包含目标串所有字符的最小子串维护 needs 和 window,用 match 变量记录匹配状态,满足时收缩 left 并更新答案
「LeetCode 438. 找到字符串中所有字母异位词」固定窗口大小(等于 p 的长度)窗口大小固定,每次左右同步滑动,比较字符频率数组是否相等

💬 面试追问模拟(提前准备,惊艳全场)

「Q1:滑动窗口有两种写法,一种是用哈希表直接跳,另一种是用集合逐个移除,有什么区别?」

直接跳(本题)性能更好,因为 left 可以一次性跳到重复位置+1,而集合方式必须每次 left++ 并移除一个字符,直到没有重复。两者都是 O(n),但常数不同。面试时推荐直接跳写法,更体现对数据结构的掌握。

「Q2:如果字符集只有 26 个小写字母,怎么优化空间?」

用一个长度为 26 的 int 数组记录每个字符的最新位置,lastPos[ch - 'a'] = right,空间 O(1) 且访问更快。

「Q3:如果题目改为“最长无重复子序列”(不要求连续),答案会怎样?」

那答案就是所有不同字符的个数(比如 “abcabcbb” 的不同字符是 a,b,c,答案为 3),问题退化为“统计不同字符数量”,与滑动窗口无关。所以连续性是本题的难点所在。


🧩 实战小技巧(刷题党必备)

  • 「口诀」:右指针探路,左指针清障,哈希表记位置,窗口长度随时算。
  • 「模板」:凡是“最长/最短子串(子数组)”且满足某种条件,优先考虑滑动窗口。
  • 「边界」:空字符串返回 0;左指针跳跃时保证left <= right + 1(不会越界)。

📈 实际应用场景(不止是刷题)

  • 「TCP 滑动窗口协议」:拥塞控制中,窗口大小动态调整,保证不丢包。
  • 「文本去重检测」:在编辑器中实时高亮重复输入的字符。
  • 「日志分析」:统计某时间窗口内不重复的 IP 访问量。
  • 「基因序列分析」:在 DNA 序列中找最长不含特定碱基的子串。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 7:05:49

六西格玛绿带vs黑带哪个好?2026年08月深度测评揭秘

开篇摘要 TL;DR&#xff1a;六西格玛绿带适合执行层&#xff0c;黑带适合管理层&#xff0c;两者在认证难度、项目规模、职业发展路径上有本质差异。本文面向采购、供应链、质量管理从业者&#xff0c;帮助你在职业进阶路上做出理性选择。 H2&#xff1a;六西格玛绿带与黑带的…

作者头像 李华
网站建设 2026/8/25 7:05:15

论文AI痕迹消除工具红黑榜:2026实测版请收好

又到毕业季&#xff0c;论文改了一版又一版&#xff0c;导师那句"这写得像AI"大概是今年最让人头皮发麻的反馈。市面上的论文AI痕迹消除工具越出越多&#xff0c;哪款真能解决问题&#xff0c;哪款只是营销做得好&#xff1f;这份红黑榜基于2026届毕业生近三个月的真…

作者头像 李华
网站建设 2026/8/25 6:59:09

WordPress/Discuz网站如何零代码接入腾讯云图片内容安全审核

1. 项目概述&#xff1a;为什么你的网站需要一个“图片安检员”做网站&#xff0c;尤其是内容型网站&#xff0c;最怕什么&#xff1f;除了服务器宕机&#xff0c;恐怕就是内容违规了。一张不合规的图片&#xff0c;轻则导致页面被屏蔽&#xff0c;重则可能让整个站点面临风险。…

作者头像 李华
网站建设 2026/8/25 6:59:03

API接口入门:从零理解AI编程与Web服务的核心对话规则

你有没有过这样的经历&#xff1a;想用某个AI模型生成一张图&#xff0c;或者调用一个翻译服务&#xff0c;却发现自己完全不知道从哪里下手&#xff1f;你打开一个项目文档&#xff0c;看到“调用我们的API即可”几个字&#xff0c;感觉像天书。或者&#xff0c;你写了个脚本想…

作者头像 李华