C++ 滑动窗口

前言

C++ 中滑动窗口分两种,一种是给定窗口长度,还有一种是不定长窗口长度。

本篇文章主要讲解这两种状态的滑动窗口,结合例题让读者更好的理解

一、给定窗口长度K

一般的,对于给定窗口长度的题,通常要求我们对窗口内的元素进行一些操作,解决一些问题,具体问题具体分析。

给定窗口长度的题目通常要求解决以下问题:

  • 找到每个窗口内的最大值或最小值。

  • 计算每个窗口的和或平均值。

  • 统计满足条件的子数组数量。

  • 找到满足条件的最长或最短子数组。

  • 统计窗口内的唯一元素数量。

可以在 O(n) 的时间复杂度内解决问题

题目1:

力扣 1343 题大小为 K 且平均值大于等于阈值的子数组数目

给你一个整数数组 arr 和两个整数 kthreshold

请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。

示例 1:

输入:arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4
输出:3
解释:子数组 [2,5,5],[5,5,5] 和 [5,5,8] 的平均值分别为 4,5 和 6 。其他长度为 3 的子数组的平均值都小于 4 (threshold 的值)。

示例 2:

输入:arr = [11,13,17,23,29,31,7,5,2,3], k = 3, threshold = 5
输出:6
解释:前 6 个长度为 3 的子数组平均值都大于 5 。注意平均值不是整数

直接上代码:

class Solution {
public:int numOfSubarrays(vector<int>& arr, int k, int threshold) {int ans = 0;int s = 0; // 维护窗口元素和for (int i = 0; i < arr.size(); i++) {// 1. 进入窗口s += arr[i];if (i < k - 1) { // 窗口大小不足 kcontinue;}// 2. 更新答案ans += s >= k * threshold;// 3. 离开窗口s -= arr[i - k + 1];}return ans;}
};

解释:总共主要分3步,不足窗口长度的先进入窗口,满足长度等于窗口大小后更新答案,之后就是窗口往后移,右边元素进入窗口,左边元素移除窗口,然后不断更新答案。

题目2:

力扣2461题长度为 K 子数组中的最大和

给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:

  • 子数组的长度是 k,且
  • 子数组中的所有元素 各不相同 。

返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。

子数组 是数组中一段连续非空的元素序列。

示例 1:

输入:nums = [1,5,4,2,9,9,9], k = 3
输出:15
解释:nums 中长度为 3 的子数组是:
- [1,5,4] 满足全部条件,和为 10 。
- [5,4,2] 满足全部条件,和为 11 。
- [4,2,9] 满足全部条件,和为 15 。
- [2,9,9] 不满足全部条件,因为元素 9 出现重复。
- [9,9,9] 不满足全部条件,因为元素 9 出现重复。
因为 15 是满足全部条件的所有子数组中的最大子数组和,所以返回 15 。

示例 2:

输入:nums = [4,4,4], k = 3
输出:0
解释:nums 中长度为 3 的子数组是:
- [4,4,4] 不满足全部条件,因为元素 4 出现重复。
因为不存在满足全部条件的子数组,所以返回 0 。

上代码看注释来理解

class Solution {
public:long long maximumSubarraySum(vector<int>& nums, int k) {int n = nums.size();  // 获取数组的长度long long sum = 0;    // 当前窗口的和long long ma = 0;     // 用于存储最大子数组和unordered_map<int, int> hash;  // 哈希表,用于记录窗口内每个元素的出现次数// 初始化窗口的前 k-1 个元素for (int i = 0; i < k - 1; i++) {hash[nums[i]]++;  // 更新元素的出现次数sum += nums[i];   // 将元素加入当前窗口的和}// 遍历数组,维护一个大小为 k 的滑动窗口for (int i = k - 1; i < n; i++) {hash[nums[i]]++;  // 将当前元素加入窗口,并更新其出现次数sum += nums[i];   // 更新当前窗口的和// 如果窗口内有 k 个不同的元素,更新最大和if (hash.size() == k) {ma = max(ma, sum);  // 更新最大子数组和}// 移动窗口:移除窗口左侧的元素hash[nums[i - k + 1]]--;  // 减少左侧元素的出现次数if (hash[nums[i - k + 1]] == 0) {hash.erase(nums[i - k + 1]);  // 如果元素的出现次数为 0,从哈希表中移除}sum -= nums[i - k + 1];  // 从当前窗口的和中移除左侧元素}return ma;  // 返回最大子数组和}
};

逻辑解释:

  1. 初始化窗口

    • 使用一个哈希表 hash 来记录窗口内每个元素的出现次数。

    • 使用 sum 来记录当前窗口的和。

    • 首先将前 k-1 个元素加入窗口,初始化 sumhash

  2. 滑动窗口遍历

    • 从第 k-1 个元素开始遍历数组。

    • 每次将当前元素 nums[i] 加入窗口,并更新其出现次数和窗口的和。

    • 检查窗口内是否有 k 个不同的元素:

      • 如果有 k 个不同的元素,更新最大和 ma

    • 移动窗口:移除窗口左侧的元素 nums[i-k+1],更新其出现次数和窗口的和。

      • 如果某个元素的出现次数变为 0,从哈希表中移除该元素。

  3. 返回结果

    • 遍历结束后,ma 中存储的就是满足条件的最大子数组和。

二、不定长窗口大小

不定长滑动窗口主要分为三类:求最长子数组,求最短子数组,以及求子数组个数

通常我们对于处理串的问题时,使用暴力算法超时的时候,就可以考虑使用滑动窗口来优化时间了

看题目来加深理解

题目1:

力扣904题水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

AC代码

class Solution {
public:int totalFruit(vector<int>& fruits) {int n = fruits.size();  // 获取果树的数量unordered_map<int, int> hash;  // 哈希表,用于记录当前窗口内每种水果的数量int left = 0;  // 滑动窗口的左边界int ma = 0;  // 用于记录最多可以采摘的水果数量// 遍历所有果树,right 表示滑动窗口的右边界for (int right = 0; right < n; right++) {hash[fruits[right]]++;  // 将当前果树的水果加入窗口,并更新其数量// 如果窗口内有超过两种水果,需要收缩窗口while (hash.size() > 2) {int out = fruits[left];  // 获取窗口左侧的水果hash[out]--;  // 减少左侧水果的数量if (hash[out] == 0) {hash.erase(out);  // 如果某种水果的数量变为 0,从哈希表中移除}left++;  // 移动左边界,缩小窗口}// 更新最多可以采摘的水果数量// 当前窗口的水果数量为 right - left + 1ma = max(ma, right - left + 1);}return ma;  // 返回最多可以采摘的水果数量}
};

很多题套路都差不多的,对于不定长滑动窗口大小,用的比较多的就是哈希表来存储

  1. 初始化

    • n:果树的总数。

    • hash:哈希表,用于记录当前窗口内每种水果的数量。

    • left:滑动窗口的左边界,初始值为0。

    • ma:用于记录最多可以采摘的水果数量,初始值为0。

  2. 滑动窗口遍历

    • 使用 right 作为滑动窗口的右边界,从左到右遍历所有果树。

    • 每次将当前果树的水果加入窗口,并更新其在哈希表中的数量。

  3. 收缩窗口

    • 如果当前窗口内有超过两种水果(hash.size() > 2),需要收缩窗口。

    • 移动左边界 left,移除窗口左侧的水果,直到窗口内只剩下两种水果。

  4. 更新结果

    • 每次调整窗口后,计算当前窗口的水果数量(right - left + 1),并更新最大值 ma

  5. 返回结果

    • 遍历结束后,ma 中存储的就是最多可以采摘的水果数量。

题目2:

力扣1695题删除子数组的最大得分

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组删除子数组的 得分 就是子数组各元素之  。

返回 只删除一个 子数组可获得的 最大得分 。

如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],...,a[r] ,那么它就是 a 的一个子数组。

示例 1:

输入:nums = [4,2,4,5,6]
输出:17
解释:最优子数组是 [2,4,5,6]

示例 2:

输入:nums = [5,2,1,2,5,2,1,2,5]
输出:8
解释:最优子数组是 [5,2,1] 或 [1,2,5]

这题和上题非常相识,都是同一个套路,变的就是题目给的条件

class Solution {
public:int maximumUniqueSubarray(vector<int>& nums) {int n = nums.size();  // 获取数组的长度long long ma = 0;     // 用于存储最大唯一子数组的和int left = 0;         // 滑动窗口的左边界long long sum = 0;    // 当前窗口内所有元素的和unordered_map<int, int> hash;  // 哈希表,用于记录窗口内每个元素的出现次数// 遍历数组,right 表示滑动窗口的右边界for (int right = 0; right < n; right++) {// 将当前元素加入窗口,并更新其出现次数hash[nums[right]]++;sum += nums[right];  // 更新当前窗口的和// 如果当前元素的出现次数大于 1,说明窗口内有重复元素// 需要收缩窗口,移除窗口左侧的元素,直到窗口内没有重复元素while (hash[nums[right]] > 1) {sum -= nums[left];  // 从窗口的和中移除左侧元素hash[nums[left]]--;  // 更新左侧元素的出现次数left++;  // 移动左边界}// 更新最大唯一子数组的和ma = max(ma, sum);}return ma;  // 返回最大唯一子数组的和}
};

万变不离其宗,只有多刷题才能加深算法的印象。祝各位读者在刷算法的路上越走越远 0v0!

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

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

相关文章

虚拟机 | Ubuntu图形化系统: open-vm-tools安装失败以及实现文件拖放

系列文章目录 虚拟机 | Ubuntu 安装流程以及界面太小问题解决 文章目录 系列文章目录虚拟机 | Ubuntu 安装流程以及界面太小问题解决 前言一、VMware Tools 和 open-vm-tools 是什么1、VMware Tools2、open-vm-tools 二、推荐使用open-vm-tools&#xff08;简单&#xff09;1、…

2025最新群智能优化算法:山羊优化算法(Goat Optimization Algorithm, GOA)求解23个经典函数测试集,MATLAB

一、山羊优化算法 山羊优化算法&#xff08;Goat Optimization Algorithm, GOA&#xff09;是2025年提出的一种新型生物启发式元启发式算法&#xff0c;灵感来源于山羊在恶劣和资源有限环境中的适应性行为。该算法旨在通过模拟山羊的觅食策略、移动模式和躲避寄生虫的能力&…

在【k8s】中部署Jenkins的实践指南

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Jenkins简介 2、k8s简介 3、什么在…

供应链重构:制造业如何借助数字化提升响应速度?

下面这篇文章旨在从宏观和微观层面探讨:在过去五年(约2020-2024年)中,制造业如何通过数字化(尤其是人工智能、物联网、大数据等技术)重构供应链,以显著提升对市场与客户需求的响应速度。本文将包含相对详实的行业数据、部分技术原理解析、以及具有代表性的案例分析,帮助…

爬虫案例十js逆向合肥滨湖会展中心网

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、网站分析二、代码总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬虫案例十js逆向合肥滨湖会展中心网 提示&#xff1a;以下…

景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石

在人工智能技术席卷全球的浪潮中&#xff0c;高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商&#xff0c;景联文科技深耕数据标注领域多年&#xff0c;以技术为基、以专业为本&#xff0c;致力于为全球客户提供全场景、高精度、多模态的数…

esp32s3聊天机器人(二)

继续上文&#xff0c;硬件软件准备齐全&#xff0c;介绍一下主要用到的库 sherpa-onnx 开源的&#xff0c;语音转文本、文本转语音、说话人分类和 VAD&#xff0c;关键是支持C#开发 OllamaSharp 用于连接ollama&#xff0c;如其名C#开发 虽然离可玩还有一段距离&#xff0…

aws(学习笔记第三十二课) 深入使用cdk(API Gateway + event bridge)

文章目录 aws(学习笔记第三十二课) 深入使用cdk学习内容&#xff1a;1. 使用aws API Gatewaylambda1.1. 以前的练习1.2. 使用cdk创建API Gateway lambda1.3. 确认cdk创建API Gateway lambda 2. 使用event bridge练习producer和consumer2.1. 代码链接2.2. 开始练习2.3. 代码部…

初识大模型——大语言模型 LLMBook 学习(一)

1. 大模型发展历程 &#x1f539; 1. 早期阶段&#xff08;1950s - 1990s&#xff09;&#xff1a;基于规则和统计的方法 代表技术&#xff1a; 1950s-1960s&#xff1a;规则驱动的语言处理 早期的 NLP 主要依赖 基于规则的系统&#xff0c;如 Noam Chomsky 提出的 生成语法&…

实现静态网络爬虫(入门篇)

一、了解基本概念以及信息 1.什么是爬虫 爬虫是一段自动抓取互联网信息的程序&#xff0c;可以从一个URL出发&#xff0c;访问它所关联的URL&#xff0c;提取我们所需要的数据。也就是说爬虫是自动访问互联网并提取数据的程序。 它可以将互联网上的数据为我所用&#xff0c;…

Net8 Spire最新版去水印,去页数限制,转word/pptx/ofd等

新建控制台程序&#xff0c;添加Spire.pdf&#xff0c;最新版本为2024年7月17日 下载连接&#xff1a; Net8 Spire最新版去水印&#xff0c;去页数限制,转word/pptx/ofd等 https://download.csdn.net/download/LongtengGensSupreme/90459916 把下载的Spire.Pdf.dll类库版本 …

MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析

MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作&#xff0c;重点讲解静态与动态 SQL 语句的拼接&#xff0c;并分析 S…

《苍穹外卖》SpringBoot后端开发项目重点知识整理(DAY1 to DAY3)

目录 一、在本地部署并启动Nginx服务1. 解压Nginx压缩包2. 启动Nginx服务3. 验证Nginx是否启动成功&#xff1a; 二、导入接口文档1. 黑马程序员提供的YApi平台2. YApi Pro平台3. 推荐工具&#xff1a;Apifox 三、Swagger1. 常用注解1.1 Api与ApiModel1.2 ApiModelProperty与Ap…

本地部署自己的多专家协作系统:环境配置篇1

本项目旨在模拟多个行业专家对问题进行精细分工&#xff0c;并逐一回答后汇总&#xff0c;从而得到更专业的回复。 链接&#xff1a;MultyAgentCollabration项目地址 配置的B站讲解视频&#xff1a;B站讲解视频 本文着重介绍环境配置方法 一定要先下拉项目哦&#xff0c;或者…

FFmpeg入门:最简单的音视频播放器

FFmpeg入门&#xff1a;最简单的音视频播放器 前两章&#xff0c;我们已经了解了分别如何构建一个简单和音频播放器和视频播放器。 FFmpeg入门&#xff1a;最简单的音频播放器 FFmpeg入门&#xff1a;最简单的视频播放器 本章我们将结合上述两章的知识&#xff0c;看看如何融…

ThinkPHP框架

在电脑C磁盘中安装composer 命令 在电脑的D盘中创建cd文件夹 切换磁盘 创建tp框架 创建一个aa的网站&#xff0c;更换路径到上一步下载的tp框架路径 在管理中修改路径 下载压缩包public和view 将前面代码中的public和view文件替换 在PHPStom 中打开文件 运行指定路径 修改demo…

HTTPS加密原理详解

目录 HTTPS是什么 加密是什么 HTTPS的工作流程 1.使用对称加密 2.引入非对称加密 3.引入证书机制 客户端验证证书真伪的过程 签名的加密流程 整体工作流程 总结 HTTPS是什么 HTTPS协议也是一个应用程协议&#xff0c;是在HTTP的基础上加入了一个加密层&#xff0c;由…

基于SpringBoot的餐厅点餐管理系统设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

第十五届蓝桥杯省赛电子类单片机学习过程记录(客观题)

客观试题: 01.典型的BUCK电源电路包含哪些关键器件(ABCD) A. 电容 B. 二极管 C. 电感 D. MOSFET 解析: 典型的 BUCK 电源电路是一种降压型的直流-直流转换电路,它包含以下关键器件: A.电容:电容在电路中起到滤波的作用。输入电容用于平滑输入电压的波动,减少电源噪声对…

基于单片机的智慧农业大棚系统(论文+源码)

1系统整体设计 经过上述的方案分析&#xff0c;采用STM32单片机为核心&#xff0c;结合串口通信模块&#xff0c;温湿度传感器&#xff0c;光照传感器&#xff0c;土壤湿度传感器&#xff0c;LED灯等硬件设备来构成整个控制系统。系统可以实现环境的温湿度检测&#xff0c;土壤…