滑动窗口模板
/* 滑动窗口算法框架 */
void slidingWindow(string s) {
unordered_map<char, int> window;
int left = 0, right = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s[right];
// 增大窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
// 注意在最终的解法代码中不要 print
// 因为 IO 操作很耗时,可能导致超时
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 缩小窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
// 其中两处 ... 表示的更新窗口数据的地方,到时候你直接往里面填就行了。
实现(C++)版
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> window;
int left = 0, right = 0;
int res = 0; // 记录结果
while (right < s.size()) {
char c = s[right];
right++;
// 进行窗口内数据的一系列更新
window[c]++;
// 判断左侧窗口是否要收缩
while (window[c] > 1) {
char d = s[left];
left++;
// 进行窗口内数据的一系列更新
window[d]--;
}
// 在这里更新答案
res = max(res, right - left);
}
return res;
}
};
// 详细解析参见:
// https://labuladong.github.io/article/?qno=3
实现(Java)版
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> window = new HashMap<>();
// https://labuladong.github.io/article/?qno=3
int left = 0, right = 0;
int res = 0;
while (right < s.length()) {
char c = s.charAt(right);
right++;
window.put(c, window.getOrDefault(c, 0) + 1);
while (window.get(c) > 1) {
char d = s.charAt(left);
left++;
window.put(d, window.get(d) - 1);
}
res = Math.max(res, right - left);
}
return res;
}
}
代码解释:
用 window.put(c, window.getOrDefault(c, 0) + 1);而不是 window.put(c, window.get(c) + 1的原因
如果字符第一次出现,get(c)方法返回的是null,如果直接使用window.get(c) + 1会出现NullPointerException,因此需要使用getOrDefault(c, 0)方法,当get(c)返回null时,返回0。这样在计算字符出现次数时,即使是第一次出现,也可以将对应的次数加1,避免了NullPointerException的出现。