当前位置: 首页 > news >正文

动态滑动窗口还搞不清?一文搞定动态滑动窗口 | 基础算法

算法简述

如果做过双指针的相关题目,很容易理解最基础的滑动窗口算法:窗口长度固定,根据条件操作窗口的移动。但是真正有灵魂的滑动窗口算法,窗口大小是动态的。如果还不了解这个算法,跟着这篇博客便能轻松入门!

算法讲解

动态的窗口大小

一般来说,滑动窗口也是用两个指针来实现,实际解决问题时主要考虑的是元素如何入窗、出窗?滑动窗口一般会依赖于序列的特点,求解有关至少至多的问题。所谓序列特点指当序列恰好满足题设条件时,更长(更短)的序列也满足要求。
由此,可以发现滑动窗口的本质就是在寻找那个恰好满足题设条件的序列【在危险的边缘反复横跳】。以求最小区间,至少元素等场景为例,指针的移动基本上遵循以下两点:

  • 满足判定条件,左指针移动,老元素出窗
  • 不满足判定条件,右指针移动,新元素入窗

相关问题

滑动窗口算法的应用场景有:

  • 子数组/子串的最值问题(如最长无重复子串、最小覆盖区间)。
  • 统计满足特定条件的连续子区间数量(如恰好/最多/最少包含k种元素)
    固定的窗口大小比较容易解决,动态的窗口大小可能需要转转变思考方式,具体会在下面的题目中分析。

题单

无重复字符的最长子串

一道典中典的滑动窗口题。窗口一直尝试扩大【右指针持续移动】,左指针负责让序列满足题设条件【一直移动到当子串没有重复字符为止】
在这里插入图片描述

int lengthOfLongestSubstring(string s) {unordered_map<char,int> m;int l = 0,r = 0;int n = s.size();int res = 0;while(r < n) {m[s[r]]++;// 当窗口内元素个数少于map的大小时// 必然存在重复的元素while(m.size() < r - l + 1){m[s[l]]--;if(m[s[l]] == 0){m.erase(s[l]);}l++;}res = max(res, r - l + 1);r++;}return res;
}

3306. 元音辅音字符串计数 II

这道题是2025.3.13的每日一题,需要转化恰好问题为至少或至多问题才容易解决。
如果想要一次遍历实现是比较困难的,因为在窗口动态变化时需要同时考虑元音的数量条件以及辅音的数量条件,分类情况较多,不好控制指针的移动。
假设题目要求统计满足恰好k个不同元素的子数组数目。若希望窗口内元素种类总等于k,那么窗口扩大时窗内元素可能种类会超过k,此时需移动左指针缩小窗口,将与新入窗元素数值相等的老元素出窗。缩小的过程中并不能保证其他元素的种类数目不变。同时如何在此过程中统计所有以右指针结尾且满足条件的子数组也是一个问题。

当统计“最多k个不同元素”的子数组数目时,窗口的右指针只需不断扩展,左指针仅在元素种类超过k时收缩。此时,每个右指针位置对应的子数组数目为right - left + 1(即以右指针结尾的所有有效子数组),直接累加即可。

恰好转化公式

根据下面这个公式,就能自由地将“恰好”问题转化为适合滑动窗口的“至多”或“至少问题。
恰好k个元素≡至少k个元素−至少k+1个元素(1)\text{恰好k个元素} \equiv \text{至少k个元素} - \text{至少k+1个元素}\tag{1} 恰好k个元素至少k个元素至少k+1个元素(1)
恰好k个元素≡至多k个元素−至多k-1个元素(2)\text{恰好k个元素} \equiv \text{至多k个元素} - \text{至多k-1个元素}\tag{2} 恰好k个元素至多k个元素至多k-1个元素(2)
在这里插入图片描述

该题中,我们使用公式(1)来转换问题。分别求每个元音字母至少出现一次且至少包含k和k+1个辅音字母的子串,然后相减即为所求。参考代码中使用map来统计子串的元音出现情况,题解中有“灵神”的更优解,使用数组与位运算来处理子串的元音信息

map<char,int> m;
bool check() {auto it = m.begin();while(it != m.end()) {if((*it).second < 1)return false;it++;}return true;
}long long cal(string& word, int k) {m['a'] = 0;m['i'] = 0;m['e'] = 0;m['o'] = 0;m['u'] = 0;int n = word.size();long long r = 0,l = 0;int cot = 0;long long res=0;while(r < n){if(m.find(word[r]) != m.end()){m[word[r]]++;}else{cot++;}while(check() && cot>=k){if(m.find(word[l]) != m.end()) {m[word[l]]--;}else {cot--;}l++;}res+=l;r++;}return res;
}long long countOfSubstrings(string word, int k) {return cal(word, k) - cal(word, k + 1);
}
http://www.dtcms.com/a/361542.html

相关文章:

  • 如何将多个Excel报表合并为一个汇总文件?
  • C++ multiset数据结构的使用情况说明
  • [界面通过zmq请求调用指定动态库函数(二)]不同动态库接口不同
  • Unity游戏打包——打包流程
  • 【开题答辩全过程】以 中华美食宝典食谱分享系统的设计与实现为例,包含答辩的问题和答案
  • HTML应用指南:利用GET请求获取MSN财经股价数据并可视化
  • 电脑没加域却能获取到IP地址
  • 力扣hot100 | 堆 | 215. 数组中的第K个最大元素、347. 前 K 个高频元素、128. 最长连续序列
  • 鞍点(Saddle Point)一文通透从曲面直觉到博弈与优化
  • 手写MyBatis第46弹:多插件责任链模式的实现原理与执行顺序奥秘--MyBatis插件架构深度解析
  • 【机器学习学习笔记】numpy基础2
  • 基于站点、模式、遥感多源降水数据融合技术应用
  • 基于单片机自行车码表/骑行运动监测
  • CVE Push Service | 高危漏洞实时情报自动化推送工具
  • Python备份实战专栏第4/6篇:Vue.js + Flask 打造企业级备份监控面板
  • SQLSERVER关键字:N
  • 构建编程知识体系:从菜鸟教程入门到指针精通的系统学习指南
  • 华东制造企业推荐的SD-WAN服务商排名
  • MySQL 8 窗口函数详解
  • 【Linux】终止线程
  • 旧物回收小程序:科技赋能,开启旧物新生之旅
  • 02-Media-1-acodec.py 使用G.711编码和解码音频的示例程序
  • 《投资-41》- 自然=》生物=》人类社会=》商业=》金融=》股市=》投资,其层层叠加构建中内在的相似的规律和规则
  • AR巡检系统:多源数据同步,开启工业智能化新纪元
  • 单链表的基本原理与实现
  • PyCharm 2025版本中新建python工程文件自动创建.venv的意义和作用
  • 【PCIE 系统】111 PCIE 设备 TYPE 0、TYPE 1
  • Google Gemini 2.5 Flash Image(Nano-Banana)震撼登场!人人都能免费用的AI修图神器!
  • 【开题答辩全过程】以 校园帮帮团跑腿系统的设计与实现为例,包含答辩的问题和答案
  • Leetcode 3664. Two-Letter Card Game