题目:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
思路:新建一个List用于存放子串,num_max存放其最大长度。遍历字符串的字符,若该字符不在list里面就把它加入list,若其在list中就先num_max=max(L.length,num_max),再删除List中其之前的所有元素(包括他本身)。最后迭代完成之后需再
num_max=max(L.length,num_max)(处理最后一个子串)。
代码如下:
public static int lengthOfLongestSubstring(String s) {
char[] str=s.toCharArray();
List<Character> L=new LinkedList<Character>();
int num_max=0;
int index=0;
for(int i=0;i<str.length;i++) {
if(!L.contains(str[i])) {
L.add(str[i]);
}else {
if(num_max<L.size()) {
num_max=L.size();
}
index=L.indexOf(str[i]);
for(int j=0;j<=index;j++) {
L.remove(0);//为啥不能是L.remove(j)呢?
}
L.add(str[i]);
}
}
if(num_max<L.size()) {
num_max=L.size();
}
return num_max;
}
以上是之前写的
优化策略:使用滑动窗口结构维持无重复子串。使用一Map结构(key : 结点, Value : 该节点最后一次出现的位置)。大体思路如下:遍历字符串,若该节点在窗口里出现过,修改该窗口的左边界为出现该节点的下一个位置。将该节点存入Map中,再将窗口右边界移动一位。此时更新最大长度变量。
具体代码如下:
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
// key char : value lastIndex
Map<Character, Integer> map = new HashMap<>();
int left = 0, right = 0, i = 0;
while(i < s.length()){
//s[i]元素在窗口中出现过
if(map.containsKey(s.charAt(i)) && map.get(s.charAt(i)) >= left){
left = map.get(s.charAt(i)) + 1;
}
map.put(s.charAt(i), i);
right = i++;
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}