滑动窗口 - LeetCode hot 100

滑动窗口 - LeetCode hot 100

@jarringslee

文章目录

什么是滑动窗口

在我目前接触到的算法题中,滑动窗口应该算是双指针的一个重要的分支应用,通常用于解决数组和字符串的区间问题。

它通过使用双指针维护一个动态窗口,在遍历数据(通常是数组或者字符串)时不断调整窗口边界,从而高效快速地找到题目要求的解。

滑动窗口的核心思想是避免重复计算,将O(n2)的暴力循环转化为O(n),更加高效。

滑动窗口的两种类型

快慢指针:用于链表中的环检测或中点查找。

左右指针:用于数组或字符串的两端向中间遍历(如二分查找或两数之和)。

滑动窗口指针:左右指针维护一个窗口,通过移动指针调整窗口范围。

算法题

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

复制代码
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。

用集合实现滑动窗口

建立双指针, 右指针往前走,直到窗口中出现相同字符(即左右指针字符相同)则左指针往前走,直到窗口中无重复字符(或指针相遇)为止。

本题可利用Set集合自动去重的特性来建立滑动窗口。右指针通过for循环来遍历字符串,期间判断Set集合中是否有重复字符,有重复就删除重复字符并走左指针,直到不重复,然后加上当前字符,更新当前窗口长度(如果比上一次大)。

js 复制代码
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let ans = 0; // 窗口长度 初始化为0
    let left = 0; // 左指针
    const window = new Set(); // 建立集合作为滑动窗口
    for (let right = 0; right < s.length; right++) {
        const str = s[right];
        while (window.has(str)) {  // while循环重复检测是否有重复
            window.delete(s[left]);
            left++; // 有的话就删除并走左指针
        }
        window.add(str); // 添加当前子串
        ans = Math.max(ans, right - left + 1); // 更新最大长度
    }
    return ans;
};

438. 找到字符串中所有字母异位词

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

复制代码
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

滑动窗口 + 哈希表判断储值是否全等

由于:"abc" "cab" 都算作 "abc" 的异位词,且在 "abcab" 中 一共出现了 "abc" "bca" "cab"三组异位词,那么我们可以:

对于和目标字符串p的比较,我们可以建立两个哈希表,储存对应的字母的出现次数;对于给定子串s,我们建立滑动窗口,用for遍历右指针:每次先储存右指针的值,然后先判断窗口长度是否超过目标串,超过就删去左指针对应的值并让左指针前移一位,最后判断长度是否相等,相等就遍历比较两个哈希表的键值对,全等就将左指针下标push进答案数组。

  • 建立哈希表,储存目标串
  • 初始化滑动窗口哈希表,左指针和答案数组
  • 利用右指针建立for循环
  • 储存右值
  • 窗口过大就删一个左值
  • 窗口相等就判断哈希表
js 复制代码
var findAnagrams = function(s, p) {
    let need = new Map();
    for (let i = 0; i < p.length; i++) {
        need.set(p[i], (need.get(p[i]) || 0) + 1);
    }
    let window = new Map();
    let left = 0;
    let ans = [];
    for (let right = 0; right < s.length; right++) {
        const str = s[right];
        window.set(str, (window.get(str) || 0) + 1);
        if (right - left + 1 > p.length) {
            if(window.get(s[left]) === 1) window.delete(s[left]);
            else window.set(s[left], window.get(s[left]) - 1);
            left++;
        } 

        if (right - left + 1 == p.length){
            let flag = true;
            for (let [key,value] of need) {
                if (window.get(key)!== value) flag=false;      
            }
            if (flag) ans.push(left);
        }

        
    }
    return ans;
};
相关推荐
2401_841495647 小时前
【数据结构】B*树
数据结构·c++·b树·算法·删除·插入·三分分裂
QXWZ_IA8 小时前
**电力登高作业高空失保实时监管:千寻智能安全带高挂低用监测方案**
人工智能·科技·算法·能源·智能硬件
爱刷碗的苏泓舒8 小时前
FFRT:固定失败率比率检验、宽巷模糊度固定及 Ratio Test
算法·相位偏差·模糊度固定·ppp-ar·ffrt·ratio test·wlnl
不简说8 小时前
# JS 代码技巧 vol.7 — 20 个浏览器 API 实战,自带 API 能干的事别自己封装
前端·javascript·面试
小园子的小菜8 小时前
深入理解 JVM 垃圾回收:从对象判定、回收算法到经典收集器全解析
jvm·算法
hold?fish:palm8 小时前
7 接雨水
开发语言·c++·leetcode
2601_954526759 小时前
【硬核长文】从卡门涡街物理方程到边缘网关温压补偿算法:工业蒸汽测控实战,深度解密靠谱的涡街流量计厂家有哪些
算法
Hilaku9 小时前
为什么 Cloudflare 能做到毫秒级冷启动,而其它云厂商却不行?
前端·javascript·程序员
2301_794461579 小时前
JavaScript 基础知识点详解
前端·javascript·html