无重复字符的最长子串
无重复字符的最长子串
题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
原始思路:将字符串转换为字符数组,遍历数组,将字符存入set集合中,利用set集合不能存储相同的元素来判断是否有相同的字符,同时记录最长数量。
if(s.length()==0){
return 0;
}
char[] c=s.toCharArray();
Set<Character> set=new HashSet<>();
int max=0,num=0;
for (int i = 0; i < c.length; i++) {
if(set.add(c[i])){
num++;
max=Math.max(num,max);
}else{
set.clear();
set.add(c[i]);
num=1;
for (int j = i-1; j >=0 ; j--) {
if(c[j]!=c[i]){
set.add(c[j]);
num++;
}else {
break;
}
}
}
}
return max;
但是这个方法的弊处也很明显,就是虽然set集合可以判断该字符前面是否已经出现过了,但是没办法记录与这个字符相等的上一个字符的位置,还需要反向遍历找到其位置,记录未重复的数量。
于是我就保着学习的念头看了一下题解,果真不出所料,找到了解决办法,代码如下:
if(s.length()==0){
return 0;
}
char[] c=s.toCharArray();
int max=0,num=0;
Map<Character,Integer> m=new HashMap<>();
for (int i = 0; i < c.length; i++) {
if(m.containsKey(c[i])){
num=Math.max(num,m.get(c[i])+1);
}
m.put(c[i],i);
max=Math.max(max,i-num+1);
}
return max;
首先,map集合有containsKey()方法可以判断是否已经存在该映射关系,这可以用来判断字符是否重复出现;其次,可以将字符与数组下标关联起来,可以通过映射关系快速的找到其下标,快速的更新未重复的最大长度。
但是这依然不是最优解,我又看到了大神的品论,下面分析一下。我们大家都知道数组是顺序存储结构,优点十分明显,查找非常快,大神也是利用了这一特点引入了一个辅助数组,其下标分别代表字符的ascll码,其存储的值表示所对应得字符在字符串中的下标。不得不说,这一步实在是妙。
int[] x=new int[128];
for (int i = 0; i < 128; i++) {
x[i]=-1;
}
int max=0,num=0,hasp;
for (int i = 0; i < s.length(); i++) {
hasp=s.charAt(i);
if(x[hasp]!=-1){
num=Math.max(num,x[hasp]+1);
}
max=Math.max(max,i-num+1);
x[hasp]=i;
}
return max;
本来我觉得这道题也就那样,但是它做出来容易,但是这个一步步优化的过程属实是让我震惊了。总的来说这道题对我的帮助很大,一是做题的方法,二是做题的思路都有很大的提升,继续加油。