跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

滑动窗口算法入门:LeetCode 经典例题解析

滑动窗口算法常用于处理数组和字符串的连续子问题。示例涵盖最小长度子数组、无重复字符最长子串、翻转 K 个零后的最大连续 1,以及将 X 减到 0 的最小操作数。核心在于双指针的移动策略与状态更新逻辑,时间复杂度优化至 O(n)。

DockerOne发布于 2026/3/21更新于 2026/7/2341 浏览
滑动窗口算法入门:LeetCode 经典例题解析

滑动窗口算法在笔试面试及竞赛中非常常见,主要用于处理数组和字符串问题,特别是涉及连续子数组或子字符串的条件筛选。所谓'滑动窗口',本质上就是维护一段区间,其大小可固定也可变化,通过左右指针的移动来扫描数据结构。基本套路通常包括:扩展右边界、检查条件、更新结果、收缩左边界。

长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其总和大于等于 target 的长度最小子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例: 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。

暴力解法需要遍历两次,时间复杂度 O(n^2),对于 n=10^5 的数据规模会超时。虽然前缀和加二分查找能达到 O(n log n),但滑动窗口可以将复杂度优化至 O(n)。

实现思路

我们维护一个滑动窗口,窗口内的值之和小于目标值时扩展右边界,一旦满足条件则尝试收缩左边界以寻找更优解。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size(), sum = 0, len = INT_MAX;
        for (int left = 0, right = 0; right < n; right++) {
            sum += nums[right]; // 进窗口
            while (sum >= target) {
                len = min(len, right - left + 1); // 判断并更新
                sum -= nums[left++]; // 出窗口
            }
        }
        return len == INT_MAX ? 0 : len;
    }
};

无重复字符的最长子串

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

示例: 输入:s = "abcabcbb" 输出:3 解释:因为无重复字符的最长子串是 "abc",所以其长度为 3。

这道题同样适用滑动窗口,约束条件变为窗口内不能有重复字符。我们需要借助哈希表(如 unordered_map)来记录字符出现的次数。

实现思路

移动右指针加入字符,若当前字符计数大于 1,说明出现重复,此时移动左指针直到移除重复字符。过程中不断更新最大长度。

class Solution {
public:
      {
        unordered_map<, > hash;
         n = s.();
         len = ;
         ( i = , j = ; j < n;) {
            hash[s[j]] += ;
             (hash[s[j]] > ) {
                hash[s[i++]]--;
            }
            len = (len, j - i + );
            j++;
        }
         len ==  ?  : len;
    }
};
int
lengthOfLongestSubstring
(string s)
char
int
int
size
int
-1
for
int
0
0
1
while
1
max
1
return
-1
0

最大连续 1 的个数 III

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0,则返回执行操作后数组中连续 1 的最大个数。

示例: 输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2 输出:6 解释:将 0 翻转为 1,最长的子数组长度为 6。

这个问题可以转化为求一个最长区间,使得区间内 0 的个数不超过 k 个。这样就能直接使用滑动窗口来处理。

实现思路

定义两个指针指向最左端,循环中统计 0 的个数。当 0 的个数超过 k 时,移动左指针直到满足条件,同时更新最终答案。

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int cnt = 0;
        int ret = -1;
        for (int i = 0, j = 0; j < n; j++) {
            if (nums[j] == 0) {
                cnt++;
            }
            while (cnt > k) {
                if (nums[i++] == 0) {
                    cnt--;
                }
            }
            ret = max(ret, j - i + 1);
        }
        return ret == -1 ? 0 : ret;
    }
};

将 x 减到 0 的最小操作数

给你一个整数数组 nums 和一个整数 x。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。如果可以将 x 恰好减到 0,返回最小操作数;否则,返回 -1。

示例: 输入:nums = [1,1,4,2,3], x = 5 输出:2 解释:最佳解决方案是移除后两个元素,将 x 减到 0。

这个题目具有迷惑性,其实可以转化一下:它问的是求一个最长的中间区间,区间里面的值等于原来数组的和减去 x。这样我们就变成了求特征子数组,可以使用滑动窗口来实现。

实现思路

第一步计算目标值,即数组总和减去 x。如果目标值小于 0 直接返回 -1。然后定义双指针,进入循环后将右指针的值加入窗口,若和大于目标值则收缩左指针。跳出循环后更新结果,最后返回数组长度减去找到的最长子数组长度。

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();
        int k = 0;
        for (auto s : nums) {
            k += s;
        }
        k -= x;
        if (k < 0) return -1;
        
        int len = -1;
        int sum = 0;
        for (int i = 0, j = 0; j < n; j++) {
            sum += nums[j]; // 进窗口
            while (sum > k) {
                sum -= nums[i++]; // 出窗口
            }
            if (sum == k) {
                len = max(len, j - i + 1);
            }
        }
        return len == -1 ? -1 : n - len;
    }
};

目录

  1. 长度最小的子数组
  2. 实现思路
  3. 无重复字符的最长子串
  4. 实现思路
  5. 最大连续 1 的个数 III
  6. 实现思路
  7. 将 x 减到 0 的最小操作数
  8. 实现思路
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • DeepSeek R1 使用指南:核心技巧与最佳实践
  • OpenClaw 及 16 款 AI Agent 工具选型指南
  • MySQL 表约束核心指南:从基础到外键实战
  • OpenClaw 多 Agent 与飞书机器人配置指南
  • 15. Web可访问性最佳实践:让每个用户都能平等访问
  • 使用 LLaMA-Factory 进行大语言模型微调详解
  • IntelliJ IDEA 5 款必备 AI 插件推荐与配置指南
  • 在 FastGPT 中接入 MCP 工具集:操作指南
  • TCP Socket 网络编程详解:API、多线程与守护进程
  • Qiskit 实战指南:IBM 量子计算开发环境搭建
  • 模板方法模式详解:抽象基类定义算法骨架
  • SRC 漏洞挖掘实战经验与技巧总结
  • Java 常用编译器优劣分析及推荐
  • JavaScript 正则表达式详解
  • 2024 年人工智能中文大模型使用指南
  • Umi 脚手架创建项目实战指南
  • Python 数据分析与可视化全面指南
  • SDXL Prompt Styler 提示词风格增强工具使用指南
  • 在 OpenClaw 中构建专业 AI 角色
  • 时序数据库选型指南:工业物联网场景首选 Apache IoTDB

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online