第一版代码,使用了hashMap,虽然ac但是效率比较低。在这里再提一下hashMap的查找效率为O(1),远高于线性表,所以可以在适当的时候使用containsKey函数。
class Solution {
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
for (int i = 0; i < s.length(); i++) {
int tempLength = 1;
Map<Character, Integer> map = new HashMap<Character, Integer>();
map.put(s.charAt(i), i);
for (int j = i + 1; j < s.length(); j++) {
if(map.containsKey(s.charAt(j)) == false) {
tempLength++;
map.put(s.charAt(j), j);
}
else {
break;
}
}
maxLength = maxLength >= tempLength ?maxLength :tempLength;
}
return maxLength;
}
}
第二版代码,利用了滑动窗口进行优化。其实就是之前扫描过一片字符串,找到一个重复字符之后,左端不是右移一个单位,而是右移到右端,右端不需要回到左端,而是同样的也右移一个字符,因为两个端点之间的字符已经被检查过,这样可以将时间复杂度优化到O(1)。
这里要注意一个细节,由于更改端点位置时没有清空hashMap,当右端扫描到重复的字符时,与其对应的字符可能出现在两个位置:出现在左端点以左的不需要处理,出现在左右端点之间的则正常移动左端点,实现在如下代码中加了注释的一行。
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<Character, Integer>();
int ans = 0;
int sLength = s.length();
int i = 0, j = 0;
while (i < sLength && j < sLength) {
if (map.containsKey(s.charAt(j))) {
// 不需要清空hashMap
i = Math.max(map.get(s.charAt(j)) + 1, i);
}
map.put(s.charAt(j), j++);
ans = Math.max(ans, j - i);
}
return ans;
}
}