题目
我的题解
题解一
把字符串分解成字符,一个个加入列表。对比新读取的字符与列表中哪一位重复,将该位之前的字符全部置零,更新最长长度。重复以上操作读完字符串。
class Solution {
public int lengthOfLongestSubstring(String s) {
int length = 0;
int max = 0;
char[] lst = new char[s.length()];
int repeatedIndex;
int thisIndex = 0;
for (int i = 0; i < s.length(); i++) {
repeatedIndex = getIndex(lst, s.charAt(i));
lst[thisIndex] = s.charAt(i);
thisIndex++;
if (repeatedIndex == -1) {
length++;
} else {
max = Math.max(max, length);
for (int j = 0; j <= repeatedIndex; j++) {
lst[j] = '\0';
}
length = i - repeatedIndex;
}
}
return Math.max(max, length);
}
public int getIndex(char[] list, char target) {
// 返回该字符的索引
for (int i = 0; i < list.length; i++) {
if (target == list[i]) {
return i;
}
}
return -1;
}
}
发现这个方法用时过多,有以下问题:
- thisIndex参数多余
- 每次从头开始查找相同字符浪费时间
- 每次将数组置零浪费时间
看了看答案,修改了代码,如下所示。
解法二 - 滑动窗口法
使用指针来替代真正去修改数组的功能,节省时间,易读性好。
class Solution {
public int lengthOfLongestSubstring(String s) {
int length = 0;
int max = 0;
char[] lst = new char[s.length()];
int repeatedIndex;
int lastIndex = 0;
for (int i = 0; i < s.length(); i++) {
repeatedIndex = getIndex(lst, lastIndex, s.charAt(i));
lst[i] = s.charAt(i);
if (repeatedIndex == -1) {
length++;
} else {
max = Math.max(max, length);
length = i - repeatedIndex;
lastIndex = repeatedIndex + 1;
}
}
return Math.max(max, length);
}
public int getIndex(char[] list, int index, char target) {
// 返回该字符的索引
for (int i = index; i < list.length; i++) {
if (target == list[i]) {
return i;
}
}
return -1;
}
}
其他题解
使用了HashMap记录,更快找到索引,详情看解法链接。
总结
- 对数组很多位进行增删改查时可以考虑滑动窗口法,可以避免复杂算法,四两拨千斤。