1.动态规划 54 ms
(1)last[] 存储当前字符的上一个相同字符的下标,-1表示在当前字符之前不存在相同的
如字符串abbac 对应的last为-1 -1 1 0 -1
(2)状态转移
start[]存储以当前字符结尾的最长子串的开始位置,也就是说此时对应的字串应该为s(start[i]…i)
对于当前位置i,
如果last[i] < start[i-1],那么位置i-1对应的子串中并没有字符s[i],此时是s[i]可以加入到i-1时的子串中,也就是说start[i] = start[i-1] + 1;
如果last[i] >= start[i-1], 那么子串s(start[i-1]…i-1)中是存在着s[i]字符的, 此时i对应的子串应该从last[i]+1开始,即重复字符的下一个字符
public class Solution {
public int lengthOfLongestSubstring(String s) {
if (null == s || 0 == s.length()){
return 0;
}
char[] sequence = s.toCharArray();
int length = sequence.length;
//last[] 存储当前字符的上一个相同字符的位置
// abbac -1 -1 1 0 -1
int[] last = new int[length];
Map<Character,Integer> map = new HashMap<Character,Integer>();
for (int i = 0; i < length ; i++){
Character ch = sequence[i];
if (map.containsKey(ch)){
last[i] = map.get(ch);
}else{
last[i] = -1;
}
map.put(ch, i);
}
//start[]存储以当前字符结尾的最长子串的开始位置
//动态转移:
//if last[i] < start[i - 1],then start[i] = start[i - 1];
//if last[i] >= start[i - 1] and last[i] <= i-1,then start[i] = last[i] + 1;
int maxLen = 1;
int start[] = new int[length];
start[0] = 0;
for (int i = 1; i < length; i++){
int start_i_1 = start[i-1];
int last_i = last[i];
if (last_i < start_i_1){
start[i] = start_i_1;
}else{
start[i] = last_i + 1;
}
maxLen = Math.max(maxLen, 1+ i - start[i]);
}
return maxLen;
}
}
2.优化 36ms
public class Solution {
public int lengthOfLongestSubstring(String s) {
if (null == s || 0 == s.length()) {
return 0;
}
char[] sequence = s.toCharArray();
int length = sequence.length;
int last, pre = 0;
int maxLen = 1;
int[] map = new int[128];
for (int i = 0; i < length; i++) {
Character ch = sequence[i];
last = map[(int) ch] - 1;
map[(int) ch] = i + 1;
pre = (last < pre) ? pre : last + 1;
maxLen = maxLen > i - pre + 1 ? maxLen : i - pre + 1 ;
}
return maxLen;
}
}