Hi 各位小伙伴今天咱们来搞定 LeetCode 第 3 题 ——无重复字符的最长子串这道题是面试高频的「滑动窗口」入门题我会用最通俗的话结合我的代码一步步讲透看完你也能轻松写出先看懂题目到底要找啥题目给我们一个字符串s要找出最长的、里面没有重复字符的连续子串返回它的长度。举个例子输入s abcabcbb→ 最长无重复子串是abc长度为 3输入s bbbbb→ 最长无重复子串是b长度为 1输入s pwwkew→ 最长无重复子串是wke长度为 3注意子串必须是连续的像pwke这种跳着选的是「子序列」不算数我的思路用「滑动窗口」找最长无重复串我最开始想暴力枚举所有子串挨个检查有没有重复字符这肯定能做但时间复杂度是 O (n²)字符串长一点就超时了。后来想到用滑动窗口双指针 哈希表的思路用两个指针l左和r右框出一个「窗口」窗口里的字符都是无重复的用哈希表记录窗口里每个字符的出现次数方便快速查重右指针r不断往右扩把新字符加进窗口如果发现重复字符就把左指针l往右挪直到窗口里没有重复字符每次调整完窗口都更新一下「最长长度」代码逐行拆解完整代码class Solution { public int lengthOfLongestSubstring(String s) { // 滑动窗口 哈希表查重 // 哈希表key字符value当前窗口内该字符出现的次数 HashMapCharacter, Integer map new HashMap(); // 左右指针l窗口左边界r窗口右边界 int l 0, r 0; // 记录最长无重复子串的长度 int maxLong 0; // 右指针一直往右走直到遍历完整个字符串 while (r s.length()) { // 1. 如果当前字符s.charAt(r)在窗口里已经出现过次数≥1 // 就把左指针往右挪直到窗口里没有重复字符 while (map.getOrDefault(s.charAt(r), 0) 1) { // 把左指针指向的字符从窗口里“移除”次数减1 map.put(s.charAt(l), map.getOrDefault(s.charAt(l), 0) - 1); // 左指针右移 l; } // 2. 现在窗口里没有重复字符了把当前字符加进窗口次数1 map.put(s.charAt(r), map.getOrDefault(s.charAt(r), 0) 1); // 3. 右指针继续往右扩 r; // 4. 更新最长长度当前窗口长度 r - l maxLong Math.max(maxLong, r - l); } // 遍历结束返回最长长度 return maxLong; } }关键步骤拆解跟着我走一遍就懂我们拿示例s abcabcbb来演示1. 初始化l0,r0,maxLong0哈希表为空右指针r从 0 开始逐个字符往后走2. 右指针扩窗口无重复时r0字符a哈希表没a直接加进去 →map{a:1}r1maxLong1r1字符b哈希表没b加进去 →map{a:1,b:1}r2maxLong2r2字符c哈希表没c加进去 →map{a:1,b:1,c:1}r3maxLong33. 遇到重复字符左指针缩窗口r3字符a哈希表a次数是 1≥1进入内层循环把l0指向的a次数减 1 →map{a:0,b:1,c:1}l1现在a次数是 0退出内层循环把a加进窗口 →map{a:1,b:1,c:1}r4maxLong还是 3窗口长度还是 34. 继续遍历直到结束后面r继续走到4b、5c…… 都会触发类似的「缩窗口」操作但最长长度始终保持 3最终返回 3。核心细节讲透1. 为什么用getOrDefaultmap.getOrDefault(s.charAt(r), 0)是为了避免null异常如果字符不在哈希表里默认返回 0代表没出现过如果在表里就返回它的出现次数方便判断是否重复2. 为什么窗口长度是r-l右指针r是已经加进窗口的下一个位置所以当前窗口里的字符是[l, r-1]长度 (r-1) - l 1 r - l直接算r-l就对了3. 内层循环的作用「去重」当右指针遇到重复字符时我们必须把左指针往右挪直到重复字符被移出窗口这样才能保证窗口里永远是「无重复字符」的子串。复杂度分析时间复杂度O (n)。每个字符最多被左指针和右指针各遍历一次所以整体是线性时间。空间复杂度O (min (m, n))。哈希表最多存m个不同字符比如字符集是 26 个字母n是字符串长度。我踩过的坑新手避坑指南忘记更新maxLong只记得扩窗口忘了每次扩完都要算一下当前窗口长度导致最后返回 0。内层循环条件写错写成map.containsKey(s.charAt(r))会导致重复字符已经被移出窗口后还在循环要判断「出现次数≥1」。窗口长度算错写成r-l1会多算一个字符因为r已经指向下一个位置了。字符串为空如果s是空串直接返回 0代码里while(rs.length())会直接不执行返回maxLong0刚好处理这种情况。小结滑动窗口解题三步口诀右指针扩窗口把新字符加进哈希表记录出现次数遇重复就缩窗口左指针往右挪直到窗口里无重复更新最长长度每次调整完窗口都算一下当前长度更新最大值