什么是滑动窗口?
操作形式上类似于队列,举个例子:abcabcbb,当abc进入窗口(队列),无重复满足题目要求,
当再进入a时,出现重复,滑动窗口将abc移出,此时剩下a;重复上述操作。
图片描述:
如何来实现它?
操作类似队列,但用队列较难实现,因为需要在队列中找到相同元素并把该元素之前的元素全部移出 。所以我们采用指针模拟滑动操作,并且为了防止开辟的空间达到O(N),我们采用相同元素覆盖法。解决覆盖问题HashMap是个不错的选择。
完整代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}
考虑到题目特殊性,因为是字符,对应的ASCII码小于128.
所以覆盖问题可以不用Hash Map来实现,定义一个数组
int[] last = new int[128];下标表示字符对应的ASCII码,值表示对应字符在字符串中的位置。当出现相同字符,下标不变,值替换即可。
class Solution {
public int lengthOfLongestSubstring(String s) {
// 用字符的ASCII码做下标,值表示在字符串中的位置
int[] last = new int[128];
//初始化都为-1
for(int i = 0; i < 128; i++) {
last[i] = -1;
}
int n = s.length();
int max = 0;
int start = 0; // 窗口开始位置
for(int i = 0; i < n; i++) {
int index = s.charAt(i);
start = Math.max(start, last[index] + 1); //滑动窗口操作
max = Math.max(max, i - start + 1); //记录最长子串
last[index] = i; //覆盖操作
}
return max;
}
}