3. 无重复字符的最长子串
思路:
题目很简单,就是普通的双指针+哈希表,于是我寻思用数组也行啊:
public int lengthOfLongestSubstring(String s) {
if(s.length() == 0) return 0;
boolean[] arr = new boolean[26];
int i = 0;
int j = 0;
int count = 1;
while(i<s.length() && j<s.length()){
if(!arr[s.charAt(j) - 'a']){
arr[s.charAt(j) - 'a'] = true;
j++;
count = Math.max(count,j-i);
}else{
while(arr[s.charAt(j) - 'a'] && i<j){
arr[s.charAt(i) - 'a'] = false;
i++;
}
}
}
return count;
}
但是错了,题目中说的是 s 由英文字母、数字、符号和空格组成🙃我又一次没看清题目,所以老老实实用哈希表吧:
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0;
int i = 0;
int j = 0;
while(i<n&&j<n){
if(!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans,j-i);
}
else{
while(i<j && set.contains(s.charAt(j))){//也可以i<=j
set.remove(s.charAt(i++));
}
}
}
return ans;
}
还有另一种更巧妙的方法,我们用map保存每个截至当前,该字符出现的最后位置,通过这个位置来更新最长字符串的起点,这样可以保证不重复,并且在这个过程中需要不断记录最大的res:
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> map = new HashMap<>();
int start = 0;
int res = 0;
for(int i=0;i<s.length();i++){
if(map.containsKey(s.charAt(i))){
start = Math.max(start,map.get(s.charAt(i))+1);
}
res = Math.max(res,i-start+1);
map.put(s.charAt(i),i);
}
return res;
}