题目
解答
题目看着不难,试了几遍,修改了一下,很快就写出以下代码
private int leetcode_3_lengthOfLongestSubstring(String s) {
int res = 0;
List<Character> characters = new ArrayList<>();
for (int i =0;i<s.length();i++){
char c = s.charAt(i);
if (characters.size()>0){
int len = characters.size();
if (characters.contains(c)){
if (len > res){
res = len;
}
int index = characters.lastIndexOf(c);
characters = characters.subList(index+1,len);
}
}
characters.add(c);
}
return res>characters.size()?res:characters.size();
}
几个测试例子都通过,一提交,发现 too young too simple,运行效率太低,需要优化算法
观摩了评论区的解答,特贴出来分享一下:
方法1:
private int leetcode_3_lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
int start = 0;
Map<Character, Integer> map = new HashMap<>();
// i用来循环字符串s中的字符,start用来记录子串起始的位置。
for (int end = 0; end < n; end++) {
// 判断是否出现重复值
if (map.containsKey(s.charAt(end))) {
// 比较看看重复值的前者是否在start位置之后(下标大于start),在start之后的话,说明在当前的区间内,
// [start,end]中存在重复值,那就是end和之前的某个值(假设下标是A)重复了,这样的话[start,end]这个区
// 间就不能用了,所以start就要变成A的下一个字符的下标map.get(s.charAt(end))。
// 如果重复值的前者在start位置之前,那么就不影响[start,end]区间,所以不用把值赋值给start。
start = Math.max(map.get(s.charAt(end)), start);
}
// 计算的子串长度,这里+1是为了加上end本身,比如start是0,end - start要比实际长度少1个,所以要+1。
ans = Math.max(ans, end - start + 1);
// 存放每个字符最后出现的位置的下一个字符的下标,用于上面start的赋值。
map.put(s.charAt(end), end + 1);
}
return ans;
}
方法2:
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
if (s != null) {
List<Character> list = new ArrayList<>(s.length());
for (int i = 0; i < s.length(); i++) {
Character character = s.charAt(i);
while (list.contains(character)) {
list.remove(0);
}
list.add(character);
maxLength = Math.max(maxLength, list.size());
}
}
return maxLength;
}
方法3:
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
int currentStart = 0;
int currentEnd = 0;
int currentMax = 0;
int[] alph = new int[255];
while((s.length() - currentStart > currentMax) && currentEnd < s.length()) {
int cN = (byte)(s.charAt(currentEnd));
if ((alph[cN] == 0) || (alph[cN] != 0 && alph[cN] <= currentStart)) {
currentMax = Math.max(currentMax, currentEnd - currentStart + 1);
alph[cN] = currentEnd + 1;
currentEnd++;
} else {
currentStart = alph[cN];
alph[cN] = currentEnd + 1;
currentEnd++;
}
}
return currentMax;
}
这个方法比较难理解,不过运行极快,打败了99.85%!