我的题解不是各大题解中最优的算法,但是我相信我的算法可以更好的理解滑动窗口的思路和原理。
先将滑动窗口的思路:
/**
*
* 什么是滑动窗口?
*
* 其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,
* 当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
*
* 如何移动?[...]表示窗口内容
*
* 示例:pwwkew -----> [p]wwkew -> [pw]wkew ->
* (下面碰到了w,**所以要去掉窗口里面的w之前的所有字符(包括w)**)
* pw[w]kew -> pw[wk]ew -> pw[wke]w -> pww[kew] --> 由此可得最大长度为3
* 我们只要把队列的左边的元素移出就行了,直到满足题目要求。
*
* 一直维持这样的队列,找出队列出现最长的长度时候
*
*/
按照这个思路,下面是我写的源码。
public static int lengthOfLongestSubstring(String s){
int num = 0;
char[] chars = s.toCharArray();
List<Character> list = new ArrayList<>();
if(s.length()==0) return 0;
else{
for (int i = 0; i < s.length(); i++) {
if(!list.contains(chars[i])){ //窗口中不包含的情况
list.add(chars[i]);
num=num>list.size()?num:list.size(); //保存最大长度
}
else { //窗口中包含待插入字符的情况
while(list.contains(chars[i])) //删除与待插入相同的字符中所有之前的字符(包含它本身)
list.remove(0);
list.add(chars[i]);
}
}
}
return num;
}
这里有个注意点,我之前提交没通过所有用例,当时我在想,把num=num>list.size()?num:list.size(); //保存最大长度加入到else里面的第一行,就是下面形式:
for (int i = 0; i < s.length(); i++) {
if(!list.contains(chars[i])){ //窗口中不包含的情况
list.add(chars[i]);
}
else { //窗口中包含待插入字符的情况
num=num>list.size()?num:list.size(); //保存最大长度
while(list.contains(chars[i])) //删除与待插入相同的字符中所有之前的字符(包含它本身)
list.remove(0); //每次去掉第一个字符(最左边)
list.add(chars[i]);
}
}
就每次添加完字符后,再算最大长度也许会更好,但是问题就出来了,当字符串的长度为1时,例如s=“a”,带入for循环,它先进入if内,加入到list后,i加1等于1,而s的长度也等于1,这样就会直接跳出for循环,那么num还是原来的初始值0,没有进入else内重新赋值,这样就存在问题了。
最后我想还是边加入字符边比较吧,这样肯定是没问题的。可能代码还有要改进的地方,欢迎各位进行友好的交流。