滑动窗口 - 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;
};
相关推荐
有点。14 小时前
C++03阶段练习(练习题)
数据结构·算法·图论
周末也要写八哥15 小时前
经典算法实例:游戏中弱角色的数量(二)
算法
是Yu欸15 小时前
鸿蒙PC移植:2048 从网页小游戏到 AI 桌面应用
大数据·人工智能·算法·数据挖掘·openharmony·codex
鹿角片ljp15 小时前
KV Cache 解析
java·算法
liliangcsdn16 小时前
IVOL与偏度因子的对比测量分析
算法
threerocks17 小时前
Jev 入门第一课
算法
西柚研究生12345618 小时前
论文分析17:YOLOv11_UAVNet:无人机航拍图像专用目标检测算法
人工智能·python·深度学习·算法·目标检测
hetao173383718 小时前
2026-09-17 hetao1733837 的刷题记录
c++·算法
午彦琳19 小时前
2026.9.17
数据结构·算法·leetcode
高级程序源20 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计