import java.util.*;
public class Solution {
// 找到字符串中最长的不包含重复字符的子字符串,返回最长子字符串的长度
// 思路:双指针遍历字符串,最后返回两个指针的差值就是最长字符串的长度
// 关键词:最长,不含重复字符
// 最长要靠双指针,重复字符要靠哈希表
// 在这段代码中,没有用到双指针,只用了一个指针回溯来遍历整个字符串,通过哈希表本身不含重复元素的性质,key为字符,value为该字符对应的index;当遇到重复的字符,就找到对应字符在当前记录的子字符串的位置,之后将该位置之前的所有字符remove。之后有一个关键点在于,当把重复位置(含重复位置)之前的字符remove后,之后的几个字符可能也已经添加到哈希表中了,我们需要通过改变right的值来将其定位到没有被遍历过的新字符的位置上,通过right = index + hashMap.size()实现。
public int lengthOfLongestSubstring (String s) {
if(s.length() == 1) return 1;
// write code here
// 指针需要回溯
int right = 0;
HashMap<Character,Integer> hashmap = new HashMap<>();
// 每次比较max和当前遍历到的字符串的长度
int max = Integer.MIN_VALUE;
while(right < s.length()){
if(!hashmap.containsKey(s.charAt(right))){
// 这里记录每次加进来的字符的key和对应位置的value
hashmap.put(s.charAt(right),right);
max = Math.max(max,hashmap.size());
right++;
}else{
// 遇到重复的字符,就找到对应字符在当前记录的子字符串的位置,之后将该位置之前的所有字符remove
max = Math.max(max,hashmap.size());
int index = hashmap.get(s.charAt(right));
for(int i = index;i>=0;i--){
hashmap.remove(s.charAt(i));
}
right = index + 1 + hashmap.size();
}
}
return max;
}
}