方法:滑动窗口
p1: hashset
HashSet hs = new HashSet<>();
//hashset保存
public int lengthOfLongestSubstring1(String s) {
HashSet<Character> hs = new HashSet<>();
int len = s.length();
int maxlen = 0;
int i = 0, j = 0;
while(i < len && j < len){
if(!hs.contains(s.charAt(j))){
hs.add(s.charAt(j));
j++;
maxlen = Math.max(maxlen, j-i); //j已经加1所以长度不需要+1
}
else{
//重点,一直移除,直到没有重复字符
hs.remove(s.charAt(i++)); //移除重复字符之前的所有字符,保证滑动窗口i-j中不重复
}
}
return maxlen;
}
p2: hashmap
HashMap<Character, Integer> hm = new HashMap<>();
//hashmap保存char和char的下标,保存滑动窗口[i,j]
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> hm = new HashMap<>();
int len = s.length();
int maxlen = 0;
// for (int j = 0, i = 0; j < n; j++) {
// if (map.containsKey(s.charAt(j))) {
// i = Math.max(map.get(s.charAt(j)), i);
// }
// ans = Math.max(ans, j - i + 1);
// map.put(s.charAt(j), j + 1);
// }
int i = 0, j = 0;
while(i < len && j < len){
//无论重不重复j都要向后,map都要保存j的值
if(!hm.containsKey(s.charAt(j))){
hm.put(s.charAt(j), j);
j++;
maxlen = Math.max(maxlen, j-i);
}
else{
//i取值重点
//i取i和当前重复值下标的下一位两者的最大值
//这样保证j再向后的之后如果与i之前的元素重复可以忽略(i不变)
//hm不必去考虑滑动窗口前的值,不会像hashset一样需要一直删除滑动窗口前面的值
i = Math.max(hm.get(s.charAt(j)) + 1, i);
hm.put(s.charAt(j), j);
j++;
maxlen = Math.max(maxlen, j-i);
}
}
return maxlen;
}