题目描述:给定一个字符串,求出改字符长中最长的,字符不重复的子串。
解题思路:这个题的关键,是对重复字符的处理,在遍历字符串的过程中,遇到了重复的字符时,需要把 已存在的重复字符和它之前的字符全删掉,从而保证新得到的字符时没有重复的。
例: abcbmc
第一次遍历:a
第二次遍历:ab
第三次遍历:abc
第四次遍历:cb 这个时候要删除前一个b和这个下标之前的字符,保证新子串是没有重复的
第五次遍历:cbm
第六次遍历:bmc 同第四次遍历,要删除前一个c和这个下标之前的字符,保证新子串是没有重复的
代码如下,这个比较好理解.
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length() == 0){
return 0;
}
int subLength=0;
int left=0;
Set<Character> set=new HashSet<>();
for(int i=0 ; i<s.length() ; i++){
Character chars=s.charAt(i);
while(set.contains(chars)){
set.remove(s.charAt(left++));
}
set.add(chars);
if(set.size() > subLength){
subLength=set.size();
}
}
return subLength;
}
}
运行结果: Runtime: 11 ms, faster than 35.25% of Java online submissions for Longest Substring Without Repeating Characters.
Memory Usage: 43.2 MB, less than 8.69% of Java online submissions for Longest Substring Without Repeating Characters. 这个解法性能相对较差。
第二种解法:我们其实只需要关心一个核心的问题。出现重复字符之后,重复字符的下标是什么值,获取到对应的值以后,就能算出当前不重复子串的长度。可以把上边解法的while循环干掉。
class Solution {
public int lengthOfLongestSubstring(String s) {
int result=0;
int[] arr=new int[256];
for(int i=0,j=0;i<s.length();i++){
//先获取下左下标,arr[s.charAt(i)]是指当前字符上一次出现的位置
j= Math.max(j,arr[s.charAt(i)]);
//把当前字符的下标更新到数组,需要+1,因为如果后面出现重复了,计算长度不会包含当前字符
arr[s.charAt(i)]=i+1;
//对比下当前子串和历史长度,区个最大值
result=Math.max(result,i-j+1);
}
return result;
}
}
运行结果: Runtime: 2 ms, faster than 99.75% of Java online submissions for Longest Substring Without Repeating Characters.
Memory Usage: 38.9 MB, less than 94.53% of Java online submissions for Longest Substring Without Repeating Characters.