【优选算法篇】:滑动窗口算法--开启高效解题的“窗口”,透过例题看奥秘

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:c++篇–CSDN博客

在这里插入图片描述

文章目录

  • 一.滑动窗口算法
  • 二.例题
    • 1.长度最小的子数组
    • 2.无重复字符的最长字串
    • 3.最大连续一的个数
    • 4.将x减到0的最小操作数
    • 5.水果成篮
    • 6.找到字符串中所有字母异位词
    • 7.串联所有单词的子串
    • 8.最小覆盖子串

一.滑动窗口算法

滑动窗口算法(Sliding Window Algorithm)是一种用于解决数组和字符串相关问题的常用算法。

  • 核心思想

    滑动窗口的核心思想是利用窗口的移动来优化问题的求解过程(通过两个指针同行移动其实就是滑动窗口),避免不必要的重复过程,从而提高算法的效率。它通过维护一个滑动窗口(窗口大小可变),也就是两个通向移动的指针再数组或者字符串上移动,比根据问题的要求进行相应的操作。

  • 关键参数

    • 窗口大小(Window Size):滑动窗口的宽度,决定了窗口中包含的元素个数。
    • 窗口位置(Window Position):由左右边界(也就是两个指针)定义的窗口在数据序列中的当前位置。
    • 滑动步长(Slide Step):每次移动窗口时跨越的数据单位数量。
    • 数据序列(Data Sequence):滑动窗口在其上进行操作的一系列数据,可以是数组,字符串等。
  • 算法流程

    1.初始化窗口:确定窗口的起始位置和结束位置,通常是数组或者字符串的开头或者任意位置。根据问题要求,确定窗口的大小和滑动规则。

    2.移动窗口:使用循环遍历数组或者字符串,根据滑动规则逐步移动窗口。通常是右指针进窗口,左指针出窗口。

    3.跟新状态:在每一步,计算或者更新窗口内的数据,并根据需要更新结果,比如窗口内的大小,最大值,最小值等变量。

    4.结束条件:当窗口的结束位置达到数组或者字符串的末尾时,算法结束。

接下来通过一些例题来讲解如何使用滑动窗口算法。这些例题也是滑动窗口算法的经典实例。

二.例题

1.长度最小的子数组

链接:leetcode.209.长度最小的子数组
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int minSubArrayLen(int target,vector<int>& nums){//滑动窗口算法int left=0;int right = 0;int sum = 0;size_t len=0;size_t minlen = -1;//右指针进窗口while(right<nums.size()){sum += nums[right];//当和大于目标值时就是左指针出窗口if(sum>=target){//注意这里一定是左指针小于等于右指针while(left<=right&&sum>=target){len = right - left + 1;if(len<minlen){minlen = len;}sum -= nums[left];left++;}}right++;}return minlen != -1 ? minlen : 0;
}

2.无重复字符的最长字串

链接:leetcode.3.无重复字符的最长子串
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int lengthOfLongestSubstring(string s) {int left = 0, right = 0;int maxlen = 0;//定义一个set类型的哈希表unordered_set<char> hash;while(right<s.size()){//进窗口pair<unordered_set<char>::iterator,bool> p=hash.insert(s[right]);//当插入失败时,也就是遇到重复字符if(p.second==false){//出窗口,移动左指针找到重复的字符位置,移动加删除while(s[left]!=*(p.first)){hash.erase(s[left++]);}//当找到重复的字符时,删除左指针指向的该字符,插入右指针指向的该字符hash.erase(s[left++]);hash.insert(s[right]);}//更新最长字串的长度maxlen = max(maxlen, right - left + 1);right++;}return maxlen;
}

3.最大连续一的个数

链接:leetcode.1004.最大连续一的个数
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int longestOnes(vector<int>& nums,int k){//定义左右指针int left = 0, right = 0;int maxlen = 0;int zero = 0;while(right<nums.size()){if(nums[right]==0){zero++;}if(zero>k){while(nums[left]){left++;}zero--;left++;}maxlen = max(maxlen, right - left + 1);right++;}return maxlen;
}

4.将x减到0的最小操作数

链接:leetcode.1658.将x减到0的最小操作数
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int minOperations(vector<int>& nums,int x){//计算数组总和int count = 0;for(auto e : nums){count += e;}//目标值等于数组总和减去xint target = count - x;//当出现特殊情况,就是目标值等于0,说明减去整个数组,直接返回数组长度,就是最小操作数if(target==0){return nums.size();}int sum = 0;int left = 0, right = 0;int maxlen = 0;while(right<nums.size()){//进窗口sum += nums[right];//当子数组和大于目标值时,出窗口if(sum>target){while(left<right&&sum>target){sum -= nums[left++];}}//当等于目标值时,就是要找的子数组,计算子数组长度并更新sum值if(sum==target){maxlen = max(maxlen, right - left + 1);sum -= nums[left++];}right++;}//如果最大数组长度不为0,最小操作数就是数组长度减去最大数组长度int minoperations=-1;if(maxlen){minoperations = nums.size() - maxlen;}return minoperations;
}

5.水果成篮

链接:leetcode.904.水果成篮
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int totalFruit(vector<int> &fruits)
{unordered_map<int, int> hash;int left = 0, right = 0;int maxlen = 0;//记录哈希桶的个数int bucket = 0;while (right < fruits.size()){// 进窗口,移动右指针hash[fruits[right]]++;//当某元素第一次插入时,桶的个数加一if (hash[fruits[right]] == 1){bucket++;}//当桶的个数大于二时,水果种类超过三种,要移除一种if (bucket > 2){//出窗口,直到桶的个数,也就是水果种类小于等于2while (left < right && bucket > 2){hash[fruits[left]]--;if (hash[fruits[left]] == 0){hash.erase(fruits[left]);bucket--;}left++;}}//更新子数组的最大长度maxlen = max(maxlen, right - left + 1);right++;}return maxlen;
}

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

链接:leetcode.438.找到字符串中所有字母异位词
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

vector<int> findAnagrams(string s,string p){//定义两个哈希表分别用来存储两个字符串,建立字符和字符个数的映射关系unordered_map<char, int> hashs;unordered_map<char, int> hashp;//定义一个数组用来存储结果vector<int> v;//定义左右指针int left=0,right=0;//定义一个变量用来记录字符的有效个数int count = 0;for(auto e : p){hashp[e]++;}while(right<s.size()){//进窗口hashs[s[right]]++;//如果哈希表s中存放字符个数小于哈希表p中的个数,count加一if(hashs[s[right]]<=hashp[s[right]]){count++;}//判断条件if(right-left+1>p.size()){//出窗口if(hashs[s[left]]<=hashp[s[left]]){count--;}hashs[s[left]]--;if(hashs[s[left]]==0){hashs.erase(s[left]);}left++;}//更新结果if(count==p.size()){v.push_back(left);}right++;}return v;
}

7.串联所有单词的子串

链接:leetcode.30.串联所有单词的字串
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

vector<int> findSubstring(string s, vector<string> &words)
{// 定义两个哈希表用来存储字符串,建立字符串和个数之间的映射关系unordered_map<string, int> hashs;unordered_map<string, int> hashw;vector<int> v;for (auto e : words){hashw[e]++;}int left = 0, right = 0;int count = 0;// len是words数组中每个单词的长度int len = words[0].size();int size = words[0].size();// pr字符串是右指针移动区间的字符串,pl字符串是左指针移动区间的字符串string pr;string pl;while (size--){while (right < s.size()){// 进窗口,每次获取len长度的字符串pr.clear();while (len && len--){pr += s[right++];}hashs[pr]++;len = words[0].size();if (hashs[pr] <= hashw[pr]){// 有效字符串的个数加一count++;}// 判断条件if ((right - left) > len * words.size()){// 左指针移动,获取len长度的字符串pl.clear();while (len && len--){pl += s[left++];}if (hashs[pl] <= hashw[pl]){count--;}hashs[pl]--;if (hashs[pl] == 0){hashs.erase(pl);}len = words[0].size();}// 更新结果if (count == words.size()){v.push_back(left);}}left = right = words[0].size() - size;count = 0;hashs.clear();}return v;
}

8.最小覆盖子串

链接:leetcode.76.最小覆盖子串
题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

string minWindow(string t, string s)
{// 定义两个哈希表,用来建立字符和个数之间的映射关系unordered_map<char, int> hasht;unordered_map<char, int> hashs;// 将字符串t的字符映射到哈希表t中int bucket = 0;for (auto e : t){hasht[e]++;// 统计哈希表t的字符种类if (hasht[e] == 1){bucket++;}}// 定义左右指针,count变量记录哈希表s中的字符种类,有效字符个数int left = 0, right = 0;int count = 0;// begin字串的起始位置,用来更新结果,minlen记录最小字串的长度int begin = -1;int minlen = INT_MAX;while (right < s.size()){// 进窗口hashs[s[right]]++;// 两个哈希表中的字符映射关系相等时,count加一if (hashs[s[right]] == hasht[s[right]]){count++;}// 判断条件,字符种类相等while (count == bucket){// 更新结果minlen = min(minlen, right - left + 1);if (minlen == right - left + 1){begin = left;}// 出窗口if (hashs[s[left]] == hasht[s[left]]){count--;}hashs[s[left]]--;if (hashs[s[left]] == 0){hashs.erase(s[left]);}left++;}right++;}// 如果没有找到,begin还是初始值返回空字符串,否则返回字串return begin == -1 ? "" : s.substr(begin, minlen);
}

以上就是关于滑动窗口算法的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/486062.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是甘特图?使用甘特图制定项目计划表的步骤

在项目管理中&#xff0c;项目计划是项目的核心要素&#xff0c;它详细记录了项目任务详情、责任人、时间规划以及所需资源。 这份计划不仅为项目推进提供指引&#xff0c;更是控制范围蔓延、争取更多支持的有力工具。 在项目管理中&#xff0c;项目计划是项目的核心要素&…

keil报错---connection refused due to device mismatch

解决办法如下&#xff1a; 记得改成1 把Enable取消

Mybaits的优点缺点?

大家好&#xff0c;我是锋哥。今天分享关于【Mybaits的优点&缺点?】面试题。希望对大家有帮助&#xff1b; Mybaits的优点&缺点? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 是一个优秀的持久层框架&#xff0c;通常用于 Java 应用程序中&…

后端-pageHelp分页查询

在pom.xml文件中先导入分页的坐标 PageResult里面有两个后端返回给前端的参数&#xff0c;我们最后把PageResult再封装到Result中&#xff0c; PageResult和Result都是工具类 EmployeeDTO中是前端页面中的模糊查询字段和分页的两个值 注意&#xff01; 括号中的参数Employee…

基于FPGA的智能电子密码指纹锁(开源全免)

基于FPGA的智能电子密码指纹锁 一、功能描述硬件资源需求 二、整体框架知识准备AS608指纹模块4*4数字键盘模块 三、Verilog代码实现以及仿真验证1.AS608_data模块2.check_hand模块3.four_four_key模块4.check_mima模块5.change_mima模块6.seg_ctrl模块7.uart_top模块8.key_debo…

静坐修心.

文章目录 打坐的历史文化渊源东方的起源与传承西方的接受与演变现代生活中的打坐 盘腿坐对身体的影响促进脊椎健康改善呼吸系统功能增强消化系统机能改善血液循环调节神经系统错误姿势及其他潜在危害 盘腿坐对心理的作用促进内心平静与放松提升自我觉察与内在探索培养专注力与精…

后端-编辑按钮的实现

编辑一共要实现两步&#xff1a; 1.点击编辑蹦出来一个弹窗&#xff0c;此时需要回显&#xff0c;根据id查出来这条数据 2.修改某些值之后点击保存的时候调用修改的接口 根据id查询的时候正常操作 修改值的时候要注意一些问题 mapper层的Employee和impl层的接收实体不一样

前端开发流程实操:从概念到上线

在前端开发这个充满创意与技术挑战的领域&#xff0c;一个清晰的开发流程是确保项目顺利进行并达到预期效果的关键。 下面就和大家分享一下前端开发的实操流程。 一、项目启动与需求分析 前端开发不是孤立的&#xff0c;它是整个项目的一部分&#xff0c;所以首先要与项目团…

IDE如何安装插件实现Go to Definition

项目背景 框架&#xff1a;Cucumber Cypress 语言&#xff1a;Javascript IDE&#xff1a;vscode 需求 项目根目录cypress-automation的cypress/integration是测试用例的存放路径&#xff0c;按照不同模块不同功能创建了很多子目录&#xff0c;cucumber测试用例.feature文…

Oracle Recovery Tools工具一键解决ORA-00376 ORA-01110故障(文件offline)---惜分飞

客户在win上面迁移数据文件,由于原库非归档,结果导致有两个文件scn不一致,无法打开库,结果他们选择offline文件,然后打开数据库 Wed Dec 04 14:06:04 2024 alter database open Errors in file d:\app\administrator\diag\rdbms\orcl\orcl\trace\orcl_ora_6056.trc: ORA-01113:…

ES使用script进行复杂排序

es数据字段&#xff0c;关注_source内容&#xff0c;为自定义的es表字段内容 {"clerk_id": 3150036230,"clerk_follow_status": 60,"create_time": 1729156110000,"channel": 1,"mid": 1538020071,"binlog_timestamp&…

【C++算法】32.前缀和_矩阵区域和

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a; 题目链接&#xff1a; 1314. 矩阵区域和 题目描述&#xff1a; 解法 防止有人看不明白题目&#xff0c;先解释一下题目 二维前缀和思想&#xff1a; 使用前缀和矩阵 ret [x1,y1]~[x2,y2] D …

【数据结构】树和森林

树的存储结构 双亲表示法 定义结构数组&#xff0c;存放树的结点&#xff0c;每个结点含两个域&#xff1a; ​ 数据域&#xff1a;存放结点信息 ​ 双亲域&#xff1a;指示结点的双亲结点在数组中的位置 typedef struct PTNode{TElemType data;int parent; }PTNode;#defi…

Thonny IDE + MicroPython + ESP32 + GY-302 测量环境中的光照强度

GY-302是一款基于BH1750FVI光照强度传感器芯片的模块。该模块能够直接测量出环境中的光照强度&#xff0c;并将光照强度转换为数字信号输出。其具体参数如下表所示。 参数名称 参数特性 测量范围 0-65535 LX 测量精度 在环境光下误差小于20%&#xff0c;能够自动忽略50/60…

智创 AI 新视界 -- AI 时代的数据隐私保护挑战与应对(16 - 3)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

网上图书购物管理系统|Java|SSM|VUE| 前后端分离

【一】可以提供远程部署安装&#xff0c;包扩环境 【二】提供软件相关的安装包 【三】如果需要提供java入门资料可咨询 【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、M…

双子气膜:科技与艺术的璀璨交融—轻空间

在城市的繁华一隅&#xff0c;即将崛起一座令人叹为观止的未来地标——双子气膜项目。这是由轻空间与国内知名企业强强联手打造的全新气膜球幕建筑&#xff0c;集合了尖端科技与视觉艺术&#xff0c;成为现代建筑领域的一次创意突破。 双子气膜&#xff1a;双球对称的震撼设计…

【全面】上市公司企业能源消耗数据(水、电、汽油、天然气、钢材等)2008-2022年

一、数据范围&#xff1a;包括水、电、汽油、天然气、钢材等3000多类能源&#xff0c;1.4万个样本。 二、资源类型&#xff1a;电 水 人均用电 人均用水 公务用车汽油 办公用水 办公用电 总行物业管理大楼办公用水 总…

双绞线直连两台电脑的方法及遇到的问题

文章目录 前言一、步骤二、问题总结&#xff1a;问题1:遇到ping不通的问题。问题2:访问其他电脑上的共享文件时提示输入网络凭证问题3:局域网共享文件时提示“没有权限访问&#xff0c;请与网络管理员联系请求访问权限” 前言 办公室里有两台电脑&#xff0c;一台装了显卡用于…

windows文件下换行, linux上不换行 解决CR换行符替换为LF notepad++

html文件是用回车换行的&#xff0c;在windows电脑上&#xff0c;显示正常。 文件上传到linux服务器后&#xff0c;文件不换行了。只有一行。而且相关js插件也没法正常运行。 用notepad查看&#xff0c;显示尾部换行符&#xff0c;是CR&#xff0c;这就是原因。CR是不被识别的。…