滑动窗口算法思想及习题

滑动窗口算法框架

在这里插入图片描述

算法的大致逻辑

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
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值