Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
public class Solution {
public int lengthOfLongestSubstring(String s) {
//方法一
// //用HashMap来存储一个字符,字符作为键,下标作为值,在相同字符时,就可以实现覆盖
// HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
// //用于标记每一次重新计算字符的起点
// int j = 0;
// int max = 0;//最大长度
// for(int i = 0;i<s.length();i++){
// //注意char是不能作为键的!!!!
// int c = s.charAt(i);
// //判断是否在map中存在了,存在了则重新选择起点
// if(map.containsKey(c)){
// //原来的位置的下一个即为起点
// //?为什么要取max不理解
// //懂了:abba是本来字第一次b和b重复时起点下标应该为2,当你往下再走到a时,map中保存着的是第一个a的下标,
// //但你的起点应该是他而应该要比他大的值,这是为了解决在选好起点后,起点字符左右会有相同的字符出现
// //所以不能单一的直接使用:map.get(c)+1,因为这样会获取到你选定的起点字符的前面的,这会出错
// j = Math.max(j,map.get(c)+1);
// }
// //将该字符和下标放入map
// map.put(c,i);
// //原来的max和现在第二个字符比较的最大长度
// max = Math.max(max,i-j+1);
// }
// return max;
//方法二,滑动窗口。
int freq[] = new int[256];
int l = 0;//区间为[l...r]
int r = -1;
int res = 0;//记录最大长度
char[] str = s.toCharArray();
//不断的移动窗口
while(l < str.length){
if(r+1 < str.length&&freq[str[r+1]]==0){
r++;
freq[str[r]]++;
}else{
freq[str[l]]--;
l++;
}
res = Math.max(res,r-l+1);
}
return res;
}
}