基础算法(5):滑动窗口

1.何为滑动窗口?

     滑动窗口其实也是一种算法,主要有两类:一类是固定窗口,一类是可变窗口。固定的窗口只需要一个变量记录,而可变窗口需要两个变量。

2.固定窗口

     就像上面这个图一样。两个相邻的长度为4的红色窗口,下一个窗口一定比前一个窗口少一个数据,以及多一个数据。

      橙色为切换窗口时少的那个数据,黄色为多出来的那个数据,所以可以直接沿用之前数据,并且减去橙色数据,加上黄色数据,就是下一个窗口的值了。这就是滑动窗口的一个经典思路。

2.1 例题解析

      首先题是这样的

给你一个整数数组arr和两个整数k和target。请你返回长度为k且平均值大于等于target的子数组数目。

       我们可以看到他已经确定了窗口的长度,像这种滑动窗口的问题,一般都是连续字串和连续子数组的问题,在我做过的题中还没有例外,这也是滑动窗口的应用限制,必须连续。下面让我们看看怎么写:

       (1)首先,统计前k个数的和sum,作为第一个窗口的值,并且判断是否满足sum>=target,如果满足,则计数器加一;

       (2)然后,窗口开始右移,以后每次通过前一个相邻窗口,计算得到下一个窗口的值,并且判断条件是否满足满足则计数器加一;

       (3)返回计数器的值;

nclude<iostream>
int numOfSubarrays(int* arr, int arrSize, int k, int target)
{int r;int sum = 0;int cnt = 0;for (r = 0; r < k; r++){sum += arr[r];}if (sum >= target)cnt++;for (r = k; r < arrSize; r++){sum -= arr[r - k];sum += arr[r];if (sum >= target)cnt++;}return cnt;
}

2.2 leetcode固定窗口题目及模板总结

2.2.1 定长字串中元音的最大数目  
class Solution {
public:int check(char c)//每次遇到一个字符都需要进行判断,所以我们自己实现一个函数,避免重复代码{if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'){return 1;}return 0;}int maxVowels(string s, int k) {int n=s.size();int r=0;//窗口边界int cnt=0;//计数器int sum=0;//比较迭代的变量for(;r<n;r++)//开始遍历{cnt+=check(s[r]);//向窗口内添加元素if(r>=k)//窗口长度大于给定值{cnt-=check(s[r-k]);滑动直到长度等于k,减去左边元素,向右不断滑动}sum=max(sum,cnt);//将sum和cnt的值进行比较,这里sum其实起到了比较作用,将cnt的值存储到sum中}return sum;}
};
2.2.2 长度最小的子数组

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int r;int result=INT32_MAX;int sum=0;int i=0;for(r=0;r<nums.size();r++){sum+=nums[r];while(sum>=target){result=min(result,r-i+1);sum-=nums[i++];}}return result==INT32_MAX?0:result;}
};

       从这两道题中我们看到了一些相似的代码,这就是

2.2.3 固定窗口长度模板
int subarrays(int* arr, int k, int target)
{ int n=arr.size();//数组长度int r;//窗口边界int cnt = 0;//一般用来求和或者计数,视题目而定int sum = 0;//比较迭代的变量for (; r < n; r++)//开始遍历{cnt += arr[r];//向窗口内添加元素if (r >= k)//窗口长度大于给定值{cnt -= arr[r - k]; //减去左边元素,向右不断滑动,直到长度等于k}sum = max(sum, cnt);//更新sum的值,将sum和cnt的值进行比较,这里sum其实起到了比较作用,将cnt的值存储到sum中}return sum;
}

3.非固定窗口

3.1 例题解析

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

     这个题怎么写呢?这个可没有说求固定长度,你翻转最多k个0之后连续1的长度最大,这个长度就是数组中连续1的最大个数,那我们就把固定长度不固定就ok了啊,下面看代码解析:

int longestOnes(vector<int>& nums, int k) {int n=nums.size();//数组/字符串长度int sum=0;//用于统计子数组/子区间是否有效,看题目要求,可能是求和/计数int l=0;//双指针,代表遍历的区间int zerocnt=0;//统计0的个数for(int r=0;r<n;r++){if(nums[r]==0)zerocnt++;//满足题目要求,计数器+1while(zerocnt>k)//翻转0的个数大于k{if(nums[l++]==0)zerocnt--;//那就开始滑动窗口了,左边界开始滑动,这时候需要判断左边界的数是不是0,是0则计数器-1,滑动到计数器的值等于k}sum=max(sum,r-l+1);//更新sum的值}return sum;}
};

     相信看完代码之后大家会发现,固定长度的滑动窗口,while循环的条件都是比较长度,而非固定长度的滑动窗口,虽然不是比较长度,但也有其他的条件进行限制,具体什么条件就需要看具体的题目了。

3.2 leetcode非固定窗口题目及模板总结

3.2.1 字符串的排列

class Solution {
public:bool checkInclusion(string s1, string s2) {//滑动窗口unordered_map<char, int> win, need;//将子串的元素压入哈希表for (auto &i : s1){++need[i];}//定义边界int right = 0, left = 0, n = s1.size(), num = s2.size(), count = 0;//进行滑动窗口for(;right < num;right++){//如果可以在哈希表中找到元素就压入到窗口中if (need.find(s2[right]) != need.end()){++win[s2[right]];if (need[s2[right]] == win[s2[right]]){++count;}}while(right - left + 1 >= n){if (count == need.size()){return true;}//缩小窗口if (need.find(s2[left]) != need.end()){//缩小窗口的步骤其实跟扩大窗口的步骤是相反的if (need[s2[left]] == win[s2[left]]){--count;}--win[s2[left]];}left++;}}return false;}
};
3.2.2 最短超串

class Solution {
public:vector<int> shortestSeq(vector<int>& big, vector<int>& small) {int n=big.size();//数组长度unordered_map<int,int>win,need;//定义两个哈希表,一个存储子数组,一个存储窗口for(auto a:small)//将子数组压入哈希表中便于查找和比较{need[a]++;}int l=0,r=0;//定义双指针(变量)作边界vector<int>ans;//定义一个数组用来存储最短子数组的左端点和右端点int count=0;//计数器,用来计算长数组出现子数组元素的次数,便于条件处理int len=INT_MAX;//可以不断更新的长度len//开始滑动窗口for(;r<n;r++){//扩大窗口if(need.find(big[r])!=need.end()){win[big[r]]++;if(need[big[r]]==win[big[r]])//防止重复{count++;  }}//开始缩小窗口while(count==need.size()){//进行获取最短超串if(len>r-l+1)//判断下一个窗口是否比上一个窗口长度小,如果小则更新len和ans数组的值{ans={l,r};len=r-l+1;}如果此时窗口左端的值在子数组的哈希表中耀进行特殊处理if(need.find(big[l])!=need.end()){if(need[big[l]]==win[big[l]]){count--;}win[big[l]]--;}l++;}}return ans;}
};
3.3.3 非固定窗口模板
int slidingWindow(vector<int> nums) {int n = nums.size();int ans = 0;// 记录窗口内的元素及其个数,非必要map<int, int> um;// l:窗口左边界; r:窗口右边界int l = 0, r = 0;// r 指针负责探索新的区间,直到搜索到nums的某末尾for(;r < n;r++) {um[r]++;// 如果区间不满足条件,l指针右移,窗口收缩while (区间[l, r] is Invalid) {um[l]--;l++;}// 此处处理结果, deal with(ans, 区间[l, r])res = max(ans, r - l + 1); // 或者res = min(ans, r - l + 1);}return ans;
}

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

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

相关文章

【PHP入门】1.3-数据类型、转换、判断

-数据类型- 数据类型&#xff1a;data type&#xff0c;在 PHP中指的是存储的数据本身的类型&#xff0c;而不是变量的类型。 PHP是一种弱类型语言&#xff0c;变量本身没有数据类型。 1.3.1PHP的八种数据类型 在PHP中将数据分为三大类八小类&#xff1a; 简单&#xff0…

Arduino外部中断按钮输入控制继电器输出

目录 一、硬件 1、硬件介绍 2、Arduino外部 &#xff08;1&#xff09;中断引脚 &#xff08;2&#xff09;中断触发方式 &#xff08;3&#xff09;中断函数 二、外部中断0 三、外部中断0、外部中断1 一、硬件 1、硬件介绍 Adruino单片机、按钮、继电器。 按钮&…

UE5 Landscape地貌制作 - 学习笔记

P2. 创建地形 https://www.bilibili.com/video/BV1mD4y1D7D6?p2&spm_id_frompageDriver&vd_source707ec8983cc32e6e065d5496a7f79ee6 新建一个Basic场景选择Landscape Mode 生成预览网格&#xff08;绿色网格&#xff09;从文件导入&#xff1a;可以导入dem高度图地貌…

二叉树【数据结构】

目录 二叉树1. 二叉树定义二叉树的存储定义 2. 遍历二叉树(1) 前序遍历(2) 中序遍历(3) 后序遍历(4) 层序遍历 3. 二叉树的相关操作(1) 二叉树的初始化(2) 二叉树的结点的手动创建(3) 二叉树结点的个数(4) 二叉树叶子结点的个数(5) 二叉树的高度(6) 第k层结点个数(7) 通过前序遍…

Linux 特殊符号

目录 1. # 注释 2. &#xff1b;命令分隔符 3. .. 上级目录 4. . 当前目录 5. " " 换行&#xff0c;解析变量 6. 换行&#xff0c;不解析变量 7. \ 和 / 8. &#xff01;历史命令调用&#xff0c;取反 9. * 通配符 10. $ 调用变量 11. | 管道 12. || …

数据结构:树(Tree)

树型结构 树的概念 树是一种非线性结构&#xff0c;他是由n&#xff08;n>0&#xff09;个有限结点组成的一个具有层次关系的集合。 当n0时&#xff0c;该树为空树。 在任意一个非空树中都满足以下条件&#xff1a; 1、有一个特殊的结点&#xff0c;称为根结点&#xff0c…

统一系统脆弱性管理平台:七大功能和漏洞说“拜拜”

由国联易安的研究团队自主研发的新一代漏洞扫描管理系统——统一系统脆弱性管理平台&#xff0c;涵盖了网络空间资产探测、系统漏洞扫描、虚拟机漏洞扫描、Web漏洞扫描、网站安全监测、数据库安全扫描、安全基线核查、工控漏洞扫描、WiFi安全检测、App安全扫描、大数据平台漏洞…

Axure

目录 一. 交互 1.2 交互事件 二. 情形 2.1 应用场景 三. 案例 3.1 ERP登录 3.2 ERP页面跳转 一. 交互 交互事件是指在用户界面中发生某些操作或行为时&#xff0c;触发相应的响应或动作。在设计网页、应用程序或其他用户界面时&#xff0c;交互事件通常用于实现交互式功…

mybatis 实现分页功能, mybatis plus 实现分页功能

目录 1 mybatis 实现分页功能2 mybatis plus 实现分页功能 1 mybatis 实现分页功能 ApiModelProperty(value "开始页")private Integer page 1;ApiModelProperty(value "每页数据个数")private Integer rows 10;以上是前端传过来的数据 Overridepublic…

Java 数据结构篇-实现二叉搜索树的核心方法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 二叉搜索树的概述 2.0 二叉搜索树的成员变量及其构造方法 3.0 实现二叉树的核心接口 3.1 实现二叉搜索树 - 获取值 get(int key) 3.2 实现二叉搜索树 - 获取最小…

Floyd求最短路(Floyd算法)

参考&#xff1a;约会怎么走到目的地最近呢&#xff1f;一文讲清所有最短路算法问题-CSDN博客 有4个城市8条路&#xff0c;公路上的数字表示这条公路的长短&#xff0c;并且路是单向的&#xff0c;现在要求我们求出任意两个城市之间的最短路程&#xff0c;也就是求任意两个点之…

Springboot项目启动前,使用GUI做初始化配置页面并将Log4j2的日志实时显示在GUI上

Springboot项目启动前&#xff0c;使用GUI做初始化配置页面并将Log4j2的日志实时显示在GUI上 效果预览 Mac Os效果图 Windows 10 效果图 需求分析 做这样的一个功能并不适用于所有系统&#xff0c;主要用于交付给用户的产品&#xff0c;这样方便客户自行维护。传统的服务一般…