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

滑动窗口的初步了解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 定义:滑动窗口
  • 一、定长滑动窗口
    • 1.定长子串中元音的最大数目
    • 2.子数组最大平均数1
    • 3.大小为K且平均值大于等于阈值的子数组数目
  • 二、不定长滑动窗口
    • 1.无重复的最长字符串
    • 2.最长和谐子序列
    • 3.乘积小于k的子数组
  • 总结


前言

本篇主要是讲的是滑动窗口的两种类型。


定义:滑动窗口

什么是滑动窗口呢?就像它的名字一样,是一个滑动的窗口。
在这里插入图片描述

一、定长滑动窗口

对于定长滑动窗口,总体来说是简单一些的,就是由于长度定了,才使得接下来解题更方便。

1.定长子串中元音的最大数目

题目传送门:定长子串中元音的最大数目
在这里插入图片描述
解决代码:

class Solution {
public:int maxVowels(string s, int k) {int n = s.size();           // 字符串长度int ans = 0;                // 当前窗口内元音字母的数量unordered_map<char, int> m; // 用于快速判断字符是否为元音的哈希表m['a'] = 1;m['e'] = 1;m['i'] = 1;m['o'] = 1;m['u'] = 1;deque<char> p;              // 存储当前窗口中的字符(实际上可以优化掉)int max1 = 0;               // 记录最大元音数量// 初始化第一个窗口(前k个字符)for(int i = 0; i < k; i++) {p.push_back(s[i]);      // 将字符加入窗口if(m.count(s[i]))       // 如果是元音字母ans++;              // 计数器加1max1 = max(ans, max1);  // 更新最大值}// 滑动窗口:从第k个字符开始,逐个移动窗口for(int i = k; i < n; i++) {if(m.count(p.front()))  // 如果窗口最左侧字符是元音ans--;              // 移除该字符后计数器减1p.pop_front();          // 移除窗口最左侧字符p.push_back(s[i]);      // 添加新字符到窗口右侧if(m.count(s[i]))       // 如果新字符是元音ans++;              // 计数器加1max1 = max(ans, max1);  // 更新最大值}return max1;                // 返回最大元音数量}
};

对于这一题关键就是维持窗口的大小,同时还要注意窗口中的值的变化,对于结果的影响。

2.子数组最大平均数1

题目传送门:子数组最大平均数1
在这里插入图片描述
解决代码:

class Solution {
public:double findMaxAverage(vector<int>& nums, int k) {int n = nums.size();           // 数组长度deque<double> p;               // 存储当前窗口中的元素(可优化)double sum = 0;                // 当前窗口的元素和double ans = -1e5;             // 最大平均值(初始化为一个很小的值)// 预处理:先将前k-1个元素加入窗口for(int i = 0; i < k-1; i++) {p.push_back(nums[i]);      // 将元素加入队列sum += nums[i];            // 累加元素和}// 滑动窗口:从第k-1个元素开始,逐个移动窗口for(int i = k-1; i < n; i++) {p.push_back(nums[i]);      // 添加新元素到窗口右侧sum += nums[i];            // 更新窗口和// 计算当前窗口的平均值并更新最大值ans = max(ans, sum / k);// 移除窗口最左侧元素,为下一次滑动做准备sum -= p.front();          // 减去左侧元素的值p.pop_front();             // 移除左侧元素}return ans;                    // 返回最大平均值}
};

其实这一题与上面的题差不多。

3.大小为K且平均值大于等于阈值的子数组数目

题目传送门:大小为K且平均值大于等于阈值的子数组数目
在这里插入图片描述
解决代码:

class Solution {
public:int numOfSubarrays(vector<int>& arr, int k, int threshold) {int n = arr.size();           // 数组长度double sum = 0;               // 当前窗口的元素和int ans = 0;                  // 符合条件的子数组数量deque<double> p;              // 存储窗口元素(可优化掉)// 预处理:计算前k-1个元素的和for(int i = 0; i < k-1; i++) {sum += arr[i];p.push_back(arr[i]);      // 将元素加入队列(后续会被移除)}// 滑动窗口处理:从第k-1个元素开始遍历到数组末尾for(int i = k-1; i < n; i++) {sum += arr[i];            // 窗口右侧新增元素p.push_back(arr[i]);      // 将元素加入队列(可优化)// 判断当前窗口平均值是否达标if(sum / k >= threshold) {ans++;                // 达标则计数器加1}// 窗口左边界右移一位sum -= p.front();         // 减去窗口左侧元素p.pop_front();            // 移除队列头部元素(可优化)}return ans;                   // 返回符合条件的子数组数量}
};

二、不定长滑动窗口

对这一类题目,写这一些题目时,我更倾向于嵌套大佬的模板
在这里插入图片描述
对于这一类,通常是把问题分解成两个状态,以此来进行窗口的变化,

1.无重复的最长字符串

题目传送门:无重复的最长字符串
在这里插入图片描述
解决代码:

class Solution {
public:int lengthOfLongestSubstring(string s) {int n=s.size();int ans=0;unordered_map<char,int>m;//来记录是否出现重复字符for(int left=0,right=0;right<n;right++){m[s[right]]++;//每次都存一下字符出现的次数while(m[s[right]]>1)//如果最右边的字符出现多次进行循环{m[s[left]]--;//最左边的下标向右移动left++;}ans=max(ans,right-left+1);//每次都判断一下ans的最大值}return ans;}
};

2.最长和谐子序列

题目传送门:最长和谐子序列
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d1cdf06774914c4f887a0d429906503f.png
由于题目所说并不是连续子序列,所以可以先进行排序之后再进行操作
解决代码:

class Solution {
public:int findLHS(vector<int>& nums) {int n=nums.size();int ans=0;sort(nums.begin(),nums.end());//先进行排序,之后寻找满足条件的子数组就简单的一些for(int left=0,right=0;right<n;right++){while((nums[right]-nums[left])>1)//其最大值与最下值的差值如果大于1就将左下标进行向右移动{left++;}if(nums[right]-nums[left]==1)//如果满足条件就进行答案的更新。ans=max(right-left+1,ans);}return ans;}
};

3.乘积小于k的子数组

题目传送门:乘积小于k的子数组
在这里插入图片描述
对于这一题同样套用上面的模板,其中的条件也要进行改变一下,其中要主义left要小于等于right
解决代码:

class Solution {
public:int numSubarrayProductLessThanK(vector<int>& nums, int k) {int n=nums.size();int ans=0;int sum=1;for(int left=0,right=0;right<n;right++){sum*=nums[right];while(sum>=k&&left<=right)//满足这些条件时,将左下标向右移动,同时也要将数据移除。{sum=sum/nums[left];left++;} ans+=right-left+1;//至于为什么该操作可以计算出结果,请看下面的解释}return ans;}
};

在这里插入图片描述


总结

当然,经过这些题目的练习,还是只能做一些浅显的题目,对于那些条件特别复杂的,还是很难理清,希望,经过接下来的练习可以更精进一些。

http://www.dtcms.com/a/270627.html

相关文章:

  • 记录一下:成功部署k8s集群(部分)
  • 【音视频】TS协议介绍
  • 搭建商城系统
  • 【Java】【力扣】3.无重复字符的最长字串
  • Flutter基础(前端教程⑧-数据模型)
  • Elasticsearch RESTful API入门:基础搜索与查询DSL
  • C#项目 在Vue/React前端项目中 使用使用wkeWebBrowser引用并且内部使用iframe网页外链 页面部分白屏
  • 数据管理新范式:基于Docker的私有云存储系统构建指南
  • 十一、K8s细粒度权限管理RBAC
  • 异步进阶:C#的Task.WhenAll——如何开启多个异步任务
  • ReactNative【实战系列教程】我的小红书 6 -- 购物(含商品搜索、商品分类、商品列表)
  • 编写产品需求文档:黄历日历小程序
  • [Leetcode] 预处理 | 多叉树bfs | 格雷编码 | static_cast | 矩阵对角线
  • React面试高频考点解析
  • LeetCode Hot 100 搜索二维矩阵 II
  • langchain从入门到精通(四十一)——基于ReACT架构的Agent智能体设计与实现
  • [附源码+数据库+毕业论]基于Spring Boot+mysql+vue结合内容推荐算法的学生咨询系统
  • RedisCommandExecutionException: ERR unknown command ‘LPOS‘
  • 树莓派5-系统 Debian 12 开启VNC远程访问踩坑记录
  • vue3面试题(个人笔记)
  • uniapp AndroidiOS 定位权限检查
  • ragflow_多模态文档解析与正文提取策略
  • 《设计模式之禅》笔记摘录 - 5.代理模式
  • Flutter基础(前端教程⑨-图片)
  • Robot之眼CMOS传感器静电防护指南
  • LeetCode热题100—— 32. 最长有效括号 (hard)
  • 零基础上手 Amazon DynamoDB:NoSQL 数据库服务的核心概念与快速搭建指南
  • Android-重学kotlin(协程源码第二阶段)新学习总结
  • 安全管理协议(SMP):配对流程、密钥生成与防中间人攻击——蓝牙面试核心考点精解
  • Qt自定义控件(9)——径向渐变QRadialGradient、圆锥渐变QConicalGradient