解
第一步,万年不变的查错。如果给的string是null或长度为0,那么直接return。
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
...
}
大致思路就是,两个pointer,前向移动第二个pointer,每次移动更新最大长度,碰到重复的,就移动第一个pointer直到没有重复的,再继续移动第二个,直到整个string被遍历完。
那么第一步,就是建一个hashmap用来去重。
Map<Character, Boolean> hash = new HashMap<>();
然后就是遍历并打擂台。如果遇到重复的,把之前遇到过的去掉,直到没有重复的为止。如果当前character不是重复的,那就更新最大length,然后记录下来遍历过这个character。遍历完后,return最大长度。
int j = 0;
int maxLength = Integer.MIN_VALUE;
for (int i = 0; i < s.length(); i++) {
while (j < s.length() && !hash.getOrDefault(s.charAt(j), false)) {
hash.put(s.charAt(j), true);
maxLength = Math.max(maxLength, j - i + 1);
j++;
}
hash.put(s.charAt(i), false);
}
return maxLength;
完整的code
public class Solution {
/*
* @param s: a string
* @return: an integer
*/
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
Map<Character, Boolean> hash = new HashMap<>();
int j = 0;
int maxLength = Integer.MIN_VALUE;
for (int i = 0; i < s.length(); i++) {
while (j < s.length() && !hash.getOrDefault(s.charAt(j), false)) {
hash.put(s.charAt(j), true);
maxLength = Math.max(maxLength, j - i + 1);
j++;
}
hash.put(s.charAt(i), false);
}
return maxLength;
}
}
分析
空间复杂度是O(n),n为s的长度。时间复杂度是O(2n),也就是O(n)。因为两个pointer遍历了string两遍。有些小的优化,比如知道s只有26个字母的话,那么不需要hashMap,可以直接用长度为26的boolean[]。如果是ASCII,那就长度为256的boolean[]。如果是unicode,还是老老实实用hashmap吧。
总的来说,这道题就是很简单的一道two pointer问题,唯一需要记住的一点就是不需要两个for loop,因为当i改变时,j不需要回到i的位置。