)
题目题目解读1.必须由原字符串中连续的一段字符组成不能跳过字符。2.子串内的任意两个字符都不相同。3.我们可以选择暴力破解美剧所有子串并检查每个子串是否有重复字符但是太慢了。换个思路考虑拿‘abcdbbacnaxd’举例无重复字符那么a开始其子串肯定不能包含a所以其实区间为abcdbb然后再依此判断开始解题一、滑动窗口 HashSet思路用 HashSet 来存储窗口内当前有哪些字符。加入新字符时如果 set 中不存在直接加入并更新长度。如果 set 中已存在说明重复此时需要循环移除左边界字符直到重复字符被移出窗口为止。核心流程1.初始化 left 0, max 0, SetCharacter set new HashSet()。2.遍历 right 从 0 到 n-1取当前字符 c s.charAt(right)。当 set 包含 c 时循环执行set.remove(s.charAt(left))。left。将 c 加入 set。用 right - left 1 更新 max。3.返回 max。代码public int lengthOfLongestSubstring(String s) { int left 0, max 0; SetCharacter set new HashSet(); for (int right 0; right s.length(); right) { char c s.charAt(right); while (set.contains(c)) { set.remove(s.charAt(left)); left; } set.add(c); max Math.max(max, right - left 1); } return max; }二、滑动窗口 HashMap跳跃收缩思路方法一的 while 循环需要一步步移动 left。如果重复字符离 left 很远比如 abcdefg...aleft 要走很多步才能把第一个 a 移除。我们可以用 HashMapCharacter, Integer 记录每个字符最近一次出现的索引。当遇到一个已经在 map 中的字符 c 时我们可以直接将 left 跳到 map.get(c) 1 的位置从而一步到位完成收缩。新的 left 不能比当前 left 小。例如 abba处理到最后一个 a 时b 的索引可能让我们把 left 跳到很早的位置这会导致窗口向左回退。因此必须取 Math.max(left, map.get(c) 1)。核心流程1.初始化 left 0, max 0, MapCharacter, Integer map new HashMap()。2.遍历 right 从 0 到 n-1取 c s.charAt(right)。如果 map 中包含 c更新 left Math.max(left, map.get(c) 1)。将 c 的最新索引 right 存入 map。更新 max Math.max(max, right - left 1)。3.返回 max。代码public int lengthOfLongestSubstring(String s) { MapCharacter, Integer map new HashMap(); int left 0, max 0; for (int right 0; right s.length(); right) { char c s.charAt(right); if (map.containsKey(c)) { left Math.max(left, map.get(c) 1); } map.put(c, right); max Math.max(max, right - left 1); } return max; }感谢您能够看到这里一起见证小何同学的算法学习如果您有不同的见解希望能得到您的指点和点悟如果您是和我一样的同学也希望这篇文章能对您有所帮助。