滑动窗口算法:双指针高效解题秘籍

一、上期回顾

掌握单调栈 核心逻辑,快速查找左右侧最值元素,搞定每日温度、下一个更大元素等经典题。今天学习滑动窗口,双指针经典算法,解决子数组、子串、区间求和类高频考题。

二、滑动窗口核心概念

滑动窗口 = 左右双指针划定一个连续区间

  • 左指针 left:窗口左边界
  • 右指针 right:窗口右边界
  • 窗口不断向右滑动,动态收缩左边界,满足题意
  • 时间复杂度:O(n),远优于暴力双重循环 O (n²)

两大分类

  1. 固定长度窗口:窗口大小固定,依次滑动统计
  2. 可变长度窗口:窗口大小不固定,求最长 / 最短合法区间

三、固定长度滑动窗口(模板)

适用:定长子数组求和、平均值、最大最小值

复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 求长度为k的子数组最大和
int maxSumFixedWindow(vector<int>& nums, int k)
{
    int sum = 0;
    // 初始化第一个窗口
    for(int i = 0; i < k; i++)
        sum += nums[i];
    int max_val = sum;
    // 滑动窗口
    for(int i = k; i < nums.size(); i++)
    {
        sum = sum - nums[i - k] + nums[i];
        max_val = max(max_val, sum);
    }
    return max_val;
}

int main()
{
    vector<int> arr = {1,3,-1,2,5};
    cout << maxSumFixedWindow(arr,3);
    return 0;
}

四、可变长度滑动窗口(通用核心模板)

通用思路

  1. 右指针不断右移扩大窗口
  2. 窗口不满足条件时,左指针右移缩小窗口
  3. 过程中记录最优答案

模板框架

复制代码
int left = 0;
for(int right = 0; right < n; right++)
{
    // 1. 加入右边界元素,更新窗口状态

    // 2. 窗口不合法,收缩左边界
    while(窗口不满足条件)
    {
        // 移除左边界元素
        left++;
    }

    // 3. 记录最优答案
}

五、经典例题 1:最长无重复子串

复制代码
int lengthOfLongestSubstring(string s)
{
    int cnt[128] = {0};
    int left = 0, res = 0;
    for(int right = 0; right < s.size(); right++)
    {
        char c = s[right];
        cnt[c]++;
        // 出现重复字符,收缩左边界
        while(cnt[c] > 1)
        {
            cnt[s[left]]--;
            left++;
        }
        res = max(res, right - left + 1);
    }
    return res;
}

六、经典例题 2:最小子数组和大于目标值

复制代码
int minSubArrayLen(int target, vector<int>& nums)
{
    int left = 0, sum = 0;
    int res = 1e9;
    for(int right = 0; right < nums.size(); right++)
    {
        sum += nums[right];
        // 满足条件就尽量缩小窗口
        while(sum >= target)
        {
            res = min(res, right - left + 1);
            sum -= nums[left];
            left++;
        }
    }
    return res == 1e9 ? 0 : res;
}

七、滑动窗口使用禁忌

滑动窗口只适用于:区间具有单调性满足:窗口扩张条件变松,窗口收缩条件变紧不适用:元素正负杂乱、无单调规律题型

八、今日核心总结

  1. 滑动窗口依靠左右双指针,线性遍历高效解题
  2. 定长窗口变长窗口两类题型
  3. 右扩左缩,先扩后缩,动态维护合法区间
  4. 字符串子串、数组子数组、区间统计优先用滑动窗口
  5. 核心口诀:右指针无脑走,不合法左指针缩

九、课后练习

  1. 用固定窗口求数组内长度为 2 的最小和
  2. 手写最长无重复子串滑动窗口代码
  3. 自行实现最短子数组满足和大于给定值
相关推荐
血色橄榄枝1 小时前
基于用户注册信息的关键词检测挑战赛「Datawhale AI 夏令营」
人工智能·算法·机器学习
Cx330❀2 小时前
【MySQL基础】一文吃透“表的约束”:从 Null/Default 到主外键的终极安全法则
linux·服务器·数据库·c++·mysql·安全
c238562 小时前
第二篇:《测试指挥官:可视化单题自测框架(含 assert 实操)》
java·数据库·c++·算法·安全性测试
辞旧 lekkk3 小时前
【Redis初阶】常见数据类型
开发语言·数据库·c++·redis·学习·缓存·bootstrap
六点_dn3 小时前
Linux学习笔记-printf命令
linux·运维·算法
遥感知识服务4 小时前
Sentinel-1 + DEM + FwDET + 随机森林:从快速水深初估到多因子误差修正
算法·随机森林·sentinel
来一碗刘肉面4 小时前
顺序表与链表的比较
数据结构·算法·链表
alphaTao4 小时前
LeetCode 每日一题 2026/7/13-2026/7/19
算法·leetcode
nnerddboy4 小时前
脑电信号处理实战 03 | 运动想象脑机接口入门:ERD/ERS、CSP 空间滤波与左右拳想象解码
算法·信号处理
持力行5 小时前
C++与Java变量声明、定义及内存分配的核心区别
java·开发语言·c++