题目链接
链接: 无重复字符的最长子串
题目要求

解题思路
这题最先想到的应该是双指针,用双指针遍历字符串,用哈希表记录字符是否重复,让 left 指向 不重复子串的最左端,right 指向最右端,求出 left 和 right - 1 之间的长度。遍历完字符串,返回最大的不重复字符串的长度。
为什么用滑动窗口?
这里举个例子:假设字符串是 d e a b c a b c a
让 right 下标去寻找不重复子串的末尾,当 right 找到重复字符停下,记录[left,right-1]区间的长度

此时如果让 left++ ,让后 right 回到 left 的位置,重新寻找不重复子串时:

会发现:如果让 right 回到 left,就意味着重新从 left 开始寻找不重复子串。这样会把之前已经检查过的字符重新检查一遍,而且可能得到更短的结果
因此用第一个 a前面的区间 作为起点时,最大长度最多就是:紫色括号的长度

这里就需要让 left 到重复字符的下一个(第一个 a 的后面),进行下一次最长子串的寻找
那么right 需要回到 left 的位置,重新寻找不重复子串吗?
答案是不需要的,因为此时区间[left right] 是没有重复字符的,right 向后继续寻找即可

因此,使用滑动窗口更契合本题。
怎么用滑动窗口
- 定义
left和right指针 - 进窗口:把字符放进
hash - 遇到重复字符,出窗口:删除
hash的重复元素 - 更新无重复字符的最长子串的长度
代码实现
java
class Solution {
public static int lengthOfLongestSubstring(String s) {
char[] arr = s.toCharArray();
//哈希表的模拟
int[] hash = new int[128]; //字符的范围 是 0 ~ 127
int len = 0;
int left = 0,right = 0;
while(right < arr.length){
//记录字符出现的次数 入窗口
hash[arr[right]]++;
//有重符字符出现就出窗口
while(hash[arr[right]] > 1){
hash[arr[left++]]--;
}
//在无重复字符时更新记录
len = Math.max(len, right - left + 1);
right++;
}
return len;
}
}