暴力,肯定超时
1. 自己想的
oN2
暴力版本的滑动窗口
对于已经通过检验的子串,一定是没有重复的。如果子串和下一个字符进行查找是否存在重复(indexOf),如果存在重复,先计算前面子串的长度,然后start就跳到存在重复的index的下一个字符,此时从start+ index + 1到end形成的子串此时还是没有重复的。
例如对于abcdebg:
- 遇到第二个b之前,子串是
abcde; - 遇到第二个b之后,计算子串长度为5,然后形成新的子串
cdeb,此时的子串仍然是没有重复元素的。 - 下一个循环继续往后进行比较
这样做的好处: 避免了每次出现重复字母后需要重新回溯到开头重新比较的问题。
java
class Solution {
public int lengthOfLongestSubstring(String s) {
// abcdeb 遇到重复的,跳到第一个b的index+1;
int n = s.length();
if(n == 0) return 0;
// 第一个元素肯定满足条件:子串为1
int res = 1;
int start = 0,end = 1;
while(end < n){
// abcd 循环到c时,取ab出来
int subIndex = s.substring(start, end).indexOf(s.charAt(end));
if(start != end && subIndex >= 0){
res = Math.max(res, end - start);
start += subIndex + 1;
}
end++;
}
res = Math.max(res, end - start);
return res;
}
}
2. 官解: 滑动窗口 + 数组
oN
我的思路没有问题,但是String.indexOf() 这个判断有没有重复字符的时候太费时间了。
- 使用一个足够长的数组
lastIndex[128]来记录字符的下一个位置 - right 向右扩展,遇到重复字符时移动 left 到重复字符的下一个位置,使子串无重复。
- 每次记录窗口的最大长度
java
class Solution {
public int lengthOfLongestSubstring(String s) {
int left = 0,maxLen = 0;
int[] lastIndex = new int[128];
for(int right = 0; right<s.length();right ++){
char c = s.charAt(right);
left = Math.max(left, lastIndex[c]);
maxLen = Math.max(maxLen, right - left + 1);
lastIndex[c] = right + 1; // 记录字符的下一个位置
}
return maxLen;
}
}