滑动窗口算法框架
算法的大致逻辑
int left = 0, right = 0;
while (right < s.size()) {
// 增大窗口
window.add(s[right]);
right++;
while (window needs shrink) {
// 缩小窗口
window.remove(s[left]);
left++;
}
}
滑动窗口算法框架
/* 滑动窗口算法框架 */
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 输出的位置 ***/
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 缩小窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
其中两处 … 表示的更新窗口数据的地方,到时候你直接往里面填就行了。
滑动窗口经典相关习题
76.最小覆盖子串
题目描述
解决代码
/**
* @param {string} s
* @param {string} t
* @return {string}
*/
var minWindow = function(s, t) {
let need = new Map()
let window = new Map()
for(let m of t) {
need.set(m, need.has(m) ? need.get(m)+1 : 1)
}
// console.log(need)
// 定义左右边界 及 有效个数
let left = 0, right = 0
let valid = 0
// 记录最小覆盖子串的起始索引及长度
let start = 0, len = Number.MAX_SAFE_INTEGER
while(right < s.length) {
// c是将移入窗口的字符
let c = s[right]
// 扩大窗口
right++
if(need.has(c)) {
window.set(c, window.has(c) ? window.get(c)+1 : 1)
if(window.get(c) == need.get(c)) valid += 1
}
// 判断左侧是否需要收缩
while(valid == need.size) {
// 更新最小覆盖子串
if(right - left < len) {
start = left
len = right - left
}
// d是将移出窗口的字符
let d = s[left]
left += 1
// 进行窗口内数据更新
if(need.has(d)) {
if(window.get(d) == need.get(d)) {
valid -= 1
}
window.set(d, window.get(d)-1)
// window.get(d)--
}
}
}
// 返回最小回文子串
return len == Number.MAX_SAFE_INTEGER ? "" : s.substr(start, len)
};
567. 字符串的排列
题目描述
解决代码
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var checkInclusion = function(s1, s2) {
let need = new Map()
let window = new Map()
for(let str of s1) {
need.set(str, need.has(str) ? need.get(str)+1 : 1)
}
let left = 0, right = 0
let valid = 0
while(right < s2.length) {
let str1 = s2[right]
right++
if(need.has(str1)) {
window.set(str1, window.has(str1) ? window.get(str1)+1 : 1)
if(need.get(str1) == window.get(str1)) valid++
}
while(right - left >= s1.length) {
if(valid == need.size) {
return true
}
let str2 = s2[left]
left++
if(need.has(str2)) {
if(need.get(str2) == window.get(str2)) valid--
}
window.set(str2, window.get(str2)-1) // window.get(str2)-- 报错 我们要具体返回相应的结果才行
}
}
return false
};
438.找到字符串中所有字母异位词
题目描述
解决代码
/**
* @param {string} s
* @param {string} p
* @return {number[]}
*/
var findAnagrams = function(s, p) {
let need = new Map()
let window = new Map()
for(let str of p) {
need.set(str, need.has(str) ? need.get(str)+1 : 1)
}
let left = 0, right = 0, valid = 0
let res = []
while(right < s.length) {
let str1 = s[right]
right++
if(need.has(str1)) {
window.set(str1, window.has(str1) ? window.get(str1)+1 : 1)
if(need.get(str1) == window.get(str1)) {
valid += 1
}
}
while(right - left >= p.length) {
if(need.size == valid) res.push(left)
let str2 = s[left]
left++
if(need.has(str2)) {
if(window.get(str2) == need.get(str2)) valid--
window.set(str2, window.get(str2)-1)
}
}
}
return res
};
3.无重复字符的最长子串
题目链接
题目描述
解决代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let window = new Map()
let left = 0, right = 0
let res = 0
while(right < s.length) {
let str = s[right]
right++
// 对window里面的数据进行更新 每次这样过去都存入到window中
window.set(str, window.has(str) ? window.get(str)+1 : 1)
// 每次对应的数值有重复的时候,扔出去即可
while(window.get(str) > 1) {
let str2 = s[left]
left++
window.set(str2,window.get(str2)-1)
}
res = Math.max(res, right-left)
}
return res
};