第三题:Longest Substring Without Repeating Characters(无重复字符的最长子串)
一、英文原题:
Given a string, find the length of the longest substring without repeating characters.
含义即:给出所给字符串的最长无重复字母的子串长度 | |
---|---|
二、整体思路:
1.首先想到的算法:直接扫描回溯寻找加上剪枝。
实际上,算不上剪枝,就是缩小解空间。
- a 使用一个set集合存储当前扫描到的子串的各个字符
- b 首先,算法从字符串左端开始依次判断每个字符
- c 如果当前检查字符不存在与set中,则将其添加到set中,并且当前判断子串长度++。否则取当前最长子串长度ret与当前判断子串长度的最大值赋予ret。之后将扫描指针回溯至上一个与当前字符相同的字符后边。
- 根据c规则从左端开始一直扫描到末尾停止
- 最后额外添加一个判断,检验当前判断子串长度是否大于当前最长子串长度,若是则更新当前最长子串长度。
实现代码如下:
private final HashSet<Character> charsPool = new HashSet<>(); //当前扫描到的子串的字符池(无重复)
public int lengthOfLongestSubstring(String s) {
int ret = 0;
char [] a = s.toCharArray();
int nowSize = 0;
for(int i = 0; i < a.length; i++) { //下一个添加入元素池的字符
if(!charsPool.add(a[i])) { //当前方法确立在字符中的各个实值相同的char其实际地址也是相同的。或者equals和hashcode已经重写过。
if(nowSize > ret) {
ret = nowSize;
}
for(int j = i-1; j >= 0;j--) {
if(a[j]==a[i]) {
i = j;
break;
}
}
nowSize = 0;
charsPool.clear();
}else {
nowSize++;
}
}
if(nowSize > ret)
ret = nowSize; //防止最后正常扫完之后没有处理
return ret;
}
2.第二个想到的算法:利用分治算法。
(未实现)
三、做题总结与感想:
思考问题的时候最好不要高估自己,一定要用纸笔将各种情况列写在纸上,确认真实可行之后再进行操作。
此外要充分考虑到提高效率时,根据各个ADT的特点而选取适合的ADT。
最重要的一点!!
一定要深挖规律,从不同角度看这个问题。
四、不足之处:
首先想到的算法由于没有没有提前缓存信息,任何东西都是现查的,所以导致效率低下,信息没有充分利用好。
如下两张图
而后看了别人的代码,既简短还高度精炼。最后发现就是因为它充分使用了map的特性。每次都将字符和当前检测到的index作为键值对put进map之中,到时候只需要根据是否有键存在即可检测有无重复字符出现。