滑动窗口详解

目录

一、滑动窗口的特定步骤:

二、题目解析

1、⻓度最⼩的⼦数组---点击跳转题目

3、最⼤连续 1 的个数 III----点击跳转题目

4、将 x 减到 0 的最⼩操作数----点击跳转题目

5、⽔果成篮----点击跳转题目


滑动窗口是双指针算法中细分的一种,它由暴力枚举算法优化而来,解决的是同向双指针问题;当一个题目在暴力解法中发现枚举时其实可以不用把“指针”往回走,就可以使用滑动窗口的思想来解决。也就是滑动窗口通过题目的某种性质,忽略了很多无效枚举,维护两个指针间的区间保持某种性质,从而把时间复杂度从O(n^2)优化到O(n)

只要题目的研究对象是一段连续区间或者能转化为一段连续区间,就可以考虑用滑动窗口来做,思路不清晰时可以先想题目的暴力枚举,从中优化而来

一、滑动窗口的特定步骤:

  • 定义指针left、right
  • 确定如何进窗口
  • 判断(指针内区的某种性质进入循环)用while循环做判断
  • 通过判断不断出窗口,使得指针内的区间满足性质
  • 确定在哪一步更新结果

滑动窗口的代码形式是双重循环,外层是right指针遍历,内层是为了指针内区间满足某种性质而不断出窗口;虽然是双重循环,但是时间复杂度只有O(n)

二、题目解析

1、⻓度最⼩的⼦数组---点击跳转题目

由于此问题分析的对象是「⼀段连续的区间」,因此可以考虑「滑动窗⼝」的思想来解决这道题。 让滑动窗⼝满⾜:从 i 位置开始,窗⼝内所有元素的和⼩于 target (那么当窗⼝内元素之和 第⼀次⼤于等于⽬标值的时候,就是 i 位置开始,满⾜条件的最⼩⻓度)。 做法:将右端元素划⼊窗⼝中,统计出此时窗⼝内元素的和:

▪ 如果窗⼝内元素之和⼤于等于 target :更新结果,并且将左端元素划出去的同时继续判 断是否满⾜条件并更新结果(因为左端元素可能很⼩,划出去之后依旧满⾜条件)

▪ 如果窗⼝内元素之和不满⾜条件: right++ ,让下⼀个元素进⼊窗⼝。

代码:

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int l = 0, r = 0;long long sum = 0;int len = INT_MAX;while(r < nums.size()){sum += nums[r];//进窗口while(sum >= target)//判断{len = min(r - l + 1,len);//更新结果sum -= nums[l++];//出窗口}r++;}return len == INT_MAX ? 0 : len;}
};

时间复杂度:虽然代码是两层循环,但是我们的 left 指针和 right 指针都是不回退的,两者 最多都往后移动 n 次。因此时间复杂度是 O(n)

2、⽆重复字符的最⻓⼦串----点击跳转题目

暴力思路:枚举「从每⼀个位置」开始往后,⽆重复字符的⼦串可以到达什么位置。找出其中⻓度最⼤的即可。在往后寻找⽆重复⼦串能到达的位置时,可以利⽤「哈希表」统计出字符出现的频次,来判断什么时候⼦串出现了重复元素。

优化:研究的对象依旧是⼀段连续的区间,因此继续使⽤「滑动窗⼝」思想来优化。
让滑动窗⼝满⾜:窗⼝内所有元素都是不重复的。
做法:右端元素 ch 进⼊窗⼝的时候,哈希表统计这个字符的频次:
▪ 如果这个字符出现的频次超过 1 ,说明窗⼝内有重复元素,那么就从左侧开始划出窗⼝,
直到 ch 这个元素的频次变为 1 ,然后再更新结果。
▪ 如果没有超过 1 ,说明当前窗⼝没有重复元素,可以直接更新结果

代码:

class Solution {
public:int lengthOfLongestSubstring(string s) {int hash[128];//下标表示字符,数组存储字符个数,可以快速查找每个字符个数int l = 0, r = 0;int len = 0;while(r < s.size()){hash[s[r]]++;//进窗口while(hash[s[r]] > 1)//判断hash[s[l++]]--;//出窗口len = max(len,r - l + 1);//更新结果r++;}return len;}
};

3、最⼤连续 1 的个数 III----点击跳转题目

不要去想怎么翻转,不要把问题想的很复杂,这道题的结果⽆⾮就是⼀段连续的 1 中间塞了 k 个 0 嘛。 因此,我们可以把问题转化成:求数组中⼀段最⻓的连续区间,要求这段区间内 0 的个数不超 过 k 个。 比特就业课 既然是连续区间,可以考虑使⽤「滑动窗⼝」来解决问题。

滑动窗口的性质:区间内至多有k个0,维护这个性质即可

代码:

class Solution {
public://转化:找到最长的子数组,0的个数不超过k个int longestOnes(vector<int>& nums, int k) {int l = 0, r = 0, len = 0;int zero = 0;while(r < nums.size()){if(nums[r] == 0) zero++;//进窗口while(zero > k)//判断性质是否满足{if(nums[l++] == 0) zero--;//出窗口}len = max(len,r - l + 1);//性质满足时更新结果r++;}return len;}
};

4、将 x 减到 0 的最⼩操作数----点击跳转题目

题⽬要求的是数组「左端+右端」两段连续的和为 x 的最短数组,正难则反,我们可以转化成求数组内⼀段连续的、和为 sum(nums) - x 的最⻓数组。此时,就是熟悉的「滑动窗⼝」问题了

target = sum - x

滑动窗口的性质:区间内和为target

题目所求的最小操作数也就是 nums的个数减去最长子数组

代码:

class Solution {
public://转化:找到最长子数组,和为 sum - xint minOperations(vector<int>& nums, int x) {int sum=0, target, len = -1;// sum = accumulate(nums.begin(), nums.end(), 0);for(auto e : nums) sum += e;target = sum - x;if(target < 0) return -1; //sum < x的情况不可能把x减为0int l = 0, r = 0;long long s = 0;//区间内的和while(r < nums.size()){s += nums[r];//进窗口while(s > target)//需要的是s等于target{s -= nums[l++];//出窗口}if(s == target) //上面循环跳出来时s可能等于或小于targetlen = max(len,r - l + 1);//更新结果r++;}if(len == -1) return len;else return nums.size() - len;}
};

5、⽔果成篮----点击跳转题目

研究的对象是⼀段连续的区间,可以使⽤「滑动窗⼝」思想来解决问题。 让滑动窗⼝满⾜:窗⼝内⽔果的种类只有两种。

做法:右端⽔果进⼊窗⼝的时候,⽤哈希表统计这个⽔果的频次。这个⽔果进来后,判断哈希表的⼤⼩:

▪ 如果⼤⼩超过 2:说明窗⼝内⽔果种类超过了两种。那么就从左侧开始依次将⽔果划出窗 ⼝,直到哈希表的⼤⼩⼩于等于 2,然后更新结果;

▪ 如果没有超过 2,说明当前窗⼝内⽔果的种类不超过两种,直接更新结果 len。

代码:

class Solution {
public://找出一个最长子数组,数组中最多两种水果int totalFruit(vector<int>& fruits) {const int N = 1e5 + 10;//下标表示水果种类,数组元素表示区间中这种水果放了几次int hash[N] = {0};int l = 0, r = 0;int kinds = 0,len = 0;//kinds表示区间内水果种类数while(r < fruits.size()){if( hash[fruits[r]]++ == 0) kinds++;while(kinds > 2){//出窗口hash[fruits[l]]--;if(hash[fruits[l]] == 0) kinds--;l++;}len = max(len,r - l + 1);r++;}return len;}
};

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

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

相关文章

SQL中为什么不要使用1=1?

为什么会使用 11&#xff1f; 在动态构建SQL查询时&#xff0c;开发者可能会不确定最终需要哪些条件。这时候&#xff0c;他们就会使用“11”作为一个始终为真的条件&#xff0c;让接下来的所有条件都可以方便地用“AND”连接起来&#xff0c;就像是搭积木的时候先放一个基座&…

安全运维 -- splunk 操作手册

0x00 背景 splunk 日常运维操作笔记。 0x01 场景 1.agent 安装 linux&#xff1a; tar -zxvf splunkforwarder-8.0.3-a6754d8441bf-Linux-x86_64.tgz -C /opt cp -r config /opt/splunkforwarder/etc/apps vi /opt/splunkforwarder/etc/apps/prefix_app_inputs/local/inputs…

PDF高效编辑器,支持修改PDF文档并转换格式从PDF文件转换成图片文件,轻松管理你的文档世界!

PDF文件已成为我们工作、学习和生活中不可或缺的一部分。然而&#xff0c;传统的PDF阅读器往往只能满足简单的查看需求&#xff0c;对于需要频繁编辑、修改或转换格式的用户来说&#xff0c;就显得力不从心。现在&#xff0c;我们为您带来一款全新的PDF高效编辑器&#xff0c;让…

挑战一周完成Vue3项目Day3: 品牌管理+平台属性管理+SPU管理+SKU管理

一、真实接口替换mock接口 &#xff08;1&#xff09;替换各个环境下的服务器地址&#xff08; .env.development、.env.production、.env.test &#xff09; VITE_SERVE"http://sph-api.atguigu.cn" &#xff08;2&#xff09; 配饰代理跨域&#xff1a;vite.con…

根据标签最大层面ROI提取原始图像区域

今天要实现的任务是提取肿瘤的感兴趣区域。 有两个文件&#xff0c;一个是nii的原始图像文件&#xff0c;一个是nii的标签文件。 我们要实现的是&#xff1a;在标签文件上选出最大层面&#xff0c;然后把最大层面的ROI映射到原始图像区域&#xff0c;在原始图像上提裁剪出ROI…

Java 高级面试问题及答案(一)

Java 高级面试问题及答案 1. 解释Java中的多线程和并发&#xff0c;并给出一个你使用多线程的场景。 答案&#xff1a; 多线程是指在程序中同时运行多个线程&#xff0c;而并发是指在多线程环境下&#xff0c;多个线程在同一个时间点上执行不同的任务。Java中的多线程可以通过…

PLC通过Modbus转Profinet网关连接变频器与电机通讯

Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;是一种能够实现Modbus协议和Profinet协议之间转换的设备。Modbus转Profinet网关可提供单个或多个RS485接口&#xff0c;PLC作为控制中枢&#xff0c;变频器作为控制电机转速&#xff0c;通过Modbus转Profinet网关&#…

机器人系统结构不确定性

定义&#xff1a;结构不确定性指的是系统的结构特性存在的不确定性。这意味着系统的动力学特性可能受到非线性、时变、时滞、饱和等因素的影响&#xff0c;导致系统的结构模型具有一定的不确定性。影响&#xff1a;结构不确定性会使得控制器的设计更加困难&#xff0c;因为传统…

瑞米派实时系统与EtherCAT移植-米尔Remi Pi

1.概述 Remi Pi采用瑞萨RZ/G2L作为核心处理器&#xff0c;该处理器搭载双核Cortex-A551.2GHzCortex-M33200MHz处理器&#xff0c;其内部集成高性能3D加速引擎Mail-G31 GPU(500MHz)和视频处理单元&#xff08;支持H.264硬件编解码&#xff09;,16位的DDR4-1600 / DDR3L-1333内存…

Webshell绕过技巧分析之-base64编码和压缩编码

在网络安全运营&#xff0c;护网HVV&#xff0c;重保等活动的过程中&#xff0c;webshell是一个无法绕过的话题。通常出现的webshell都不是以明文的形式出现&#xff0c;而是针对webshell关键的内容进行&#xff0c;混淆&#xff0c;编码来绕过网络安全产品&#xff0c;例如IDS…

计算机提示msvcp110.dll是什么意思?msvcp110.dll丢失恢复办法

在Windows操作系统中&#xff0c;动态链接库&#xff08;DLL&#xff09;扮演着至关重要的角色&#xff0c;它们是实现程序间代码共享和模块化设计的关键组件。msvcp110.dll&#xff0c;作为Microsoft Visual C 2012运行时库的一个组成部分&#xff0c;是理解现代软件开发和维护…

【酱浦菌-爬虫技术细节】解决学术堂爬虫翻页(下一页)问题

首先我们通过css选择器获取页码信息&#xff0c;这里的css选择器&#xff0c;选择的是含有a标签的所有li标签&#xff0c;代码如下&#xff1a; li html_web.css(div.pd_c_xslb_left_fenye ul li>a) for li in li:li_url li.css(a::attr(href)).get()li_num li.css(a::t…

Java中的public,private,protect,默认这几个访问修饰符的范围和概念

在Java中&#xff0c;public、private和protected是访问修饰符&#xff0c;它们决定了类、方法或变量的访问级别。这些访问修饰符有助于实现封装&#xff0c;这是面向对象编程的四大基本特性之一。 public&#xff1a;这是最高级别的访问修饰符。被public修饰的类、方法或变量…

STM32入门_江协科技_3~4_OB记录的自学笔记_软件安装新建工程

3. 软件安装 3.1. 安装Keil5 MDK 作者的资料下载的连接如下&#xff1a;https://jiangxiekeji.com/download.html#32 3.2. 安装器件支持包 因为新的芯片层出不穷&#xff0c;所以需要安装Keil5提供的器件升级版对软件进行升级&#xff0c;从而支持新的芯片&#xff1b;如果不…

python Django 的内置权限系统或自定义模型来存储更复杂的角色和权限关系

在 Django 中,管理用户权限和角色通常涉及到使用 Django 的内置权限系统或自定义模型来存储更复杂的角色和权限关系。下面是一个基本的指南,说明如何在 Django 中为后台管理系统分配权限并将其保存在数据库中,同时结合 Vue.js 和 Element UI 作为前端框架。 后端(Django)…

unity-C#调用百度千帆AppBuilder的OpenApi

目录 功能描述准备工作百度智能云账号创建应用编辑应用创建Api秘钥Api调用流程unity代码Unitywebrequest非流式流式注意事项 Restsharp 功能描述 使用百度千帆AppBuilder平台,通过api调用的方式实现AI大模型对话功能(文字) 准备工作 百度智能云账号 请自行在百度智能云进行…

力扣---二叉树的右视图

给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,null,3] 输出: [1,3]示例 3: 输入: [] 输出: []实现方法&…

深度学习框架pytorch入门与实践

深度学习框架pytorch是由Facebook开发的一种开源机器学习库&#xff0c;它可以用于构建和训练神经网络模型。本文将介绍pytorch的入门知识和实践技巧。 安装pytorch 首先&#xff0c;你需要在你的机器上安装pytorch。可以通过以下命令安装&#xff1a; pip install torch to…

nginx+Tomcat动静分离

本⽂的动静分离主要是通过nginxtomcat来实现&#xff0c;其中nginx处理图⽚、html等静态的⽂ 件&#xff0c;tomcat处理jsp、do等动态⽂件. 实验环境 192.168.200.133 nginx反向代理 192.168.200.129 static 192.168.200.130 dynamic 步骤 修改三台主机名 [rootadmin ~]#…

关于Centos 7/8 网络设置 与工具连接

网络三步曲的配置 1、首先更改虚拟机的网络配置 查看子网地址以及网关 如果有要求需要更改IP地址&#xff0c;规定第三位是指定数值&#xff0c;那么需要全部更改 例如&#xff0c;IP地址为192.168.200.30 其中200为重点&#xff0c;更改时为以下步骤 1、点击DHCP设置&#x…