滑动窗口专题

通过以下几道题来熟悉滑动窗口
滑动窗口3大问题:如何移入窗口,如何移出窗口,如何更新答案

209. 长度最小的子数组

 我们考虑通过窗口来计算和,快慢指针从左开始遍历。

移入窗口:直接把当前元素加进来。
移出窗口:如果和大于target就把左边移出,看看窗口变小了还是否满足。
更新答案:在移出窗口前记录当前长度与之前的结果取min。

简单分析一下这样是否一定能得出正确答案:假设答案是数组中的某一段,那么这个答案一定是从砍去左端一点一点移出来的,也就是我们会找到最终结果。

代码如下:

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size();int sum = 0;int ant = INT_MAX;//存答案for (int i = 0, j = 0; i < n; i++) {sum += nums[i];//移入窗口while (i >= j && sum >= target) {//当前窗口满足题意了,看看变小是否满足ant = min(ant, i - j + 1);//更新答案sum -= nums[j++];//移出窗口}}return ant == INT_MAX ? 0 : ant;//ant没变过说明整个数组所有值加起来也到不了target,返回0}
};

3. 无重复字符的最长子串

跟上一题有点像,上一题为最短,这题为最长。

我们想一下如何用滑动窗口3步来实现

移入窗口:把当前字符放入窗口
移出窗口:窗口中有重复字符时,移动左端,直到无重复字符
更新答案:无重复字符就与之前存的结果取max

简单分析一下这样是否一定能得出正确答案:假设答案是字符串中的某一段,那么这个答案左边第一个一定与窗口内字符相重,该操作也是我们移出窗口能得到的,也就是我们会找到最终结果。

代码如下:

class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_map<char, int> m;//统计窗口内字符种类和数量int n = s.size();int ant = 0; //答案for (int i = 0, j = 0; i < n; i++) {m[s[i]]++;//移入窗口while (j <= i && m[s[i]] > 1) {m[s[j]]--;//有重复的移出窗口j++;}ant = max(ant, i - j + 1);//更新答案}return ant;}
};

76. 最小覆盖子串

这个题难度就来了,我们看看它比前两个难在哪,又该怎么处理

我们想一下,首先得遍历字符串t,看看它有多少种字符,每种字符有多少个。

然后遍历字符串s看看,哪一段满足且是最短的。如果s能覆盖t,那最长肯定是s,最短的情况是中间的某一段,也是可以通过窗口移出来的。

移入窗口:当前字符放进来,看看这个字符是否覆盖
移出窗口:如果所有字符都覆盖则移出左端看看是否还覆盖
更新答案:如果所有字符都覆盖就统计一下左右端点,取长度最小,最后截取一下字符串即可 

代码如下:

class Solution {
public:string minWindow(string s, string t) {int ls = s.size();unordered_map<char, int> ms, mt;int left = -1, right = 100005; //存答案for (auto i : t)mt[i]++;  //遍历一下看看每种字符有多少个int num = mt.size();//算算有多少种字符未被覆盖for (int i = 0, j = 0; i < ls; i++) {if (++ms[s[i]] == mt[s[i]])//当前字符加入窗口num--;  //如果该字符被覆盖了则减1while (j <= i && num == 0) {//全覆盖了if (right - left + 1 > i - j + 1)//比较长度left = j, right = i;//更新答案if (--ms[s[j]] < mt[s[j]])num++;//移出窗口,移出后不覆盖则num++j++;}}return right - left > ls ? "" : s.substr(left, right - left + 1);//right-left为初始值则返回空字符串,否则截取所需字符串}
};

这道题主要多了一步移入移出额外判断 

134. 加油站

这道题用了环形数组,我们采用倍增来处理,并依然可以采用滑动窗口来解决。

我们想一下如果从某站开始无法绕一圈,那一定会在中间停下,这时我们只需把起始点去掉,从它的下一点开始看看能不能绕一圈,这就蕴含滑窗的思想。

移入窗口:加入当前站汽油,减去到下一站消耗汽油 
移出窗口:如果汽油不够了,去掉起始站再判断。
更新答案:走的站数量为一圈的数量时,返回答案

代码如下:

class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int n = gas.size();int sum = 0;  //sum大于0表示能到下一站gas.insert(gas.end(), gas.begin(), gas.end());//倍增处理循环cost.insert(cost.end(), cost.begin(), cost.end());for (int i = 0, j = 0; i < 2 * n; i++) {sum += gas[i] - cost[i];//移入窗口while (j <= i && sum < 0) {//移出窗口sum -= gas[j] - cost[j];//绕不了一圈,把起始减去j++;}if (i - j + 1 == n) return j;//如果长度为n则绕一圈了//更新答案,直接返回}return -1;}
};

这个题有一个循环要求,我们可以倍增来解决

1234. 替换子串得到平衡字符串

我们想一下是要替换字符串,也就是窗口内字符串是不要的,那它有什么性质吗?能判断如何移出移入吗?简单想一下发现比较困难,所以我们转换思路,看看窗口外有什么性质。

我们发现如果要替换,则一定有字符长度大于l/4,而要替换的字符串一定包含这些,并只能大于等于它,那么外面的每种字符数量一定小于等于l/4,那么这时窗口内字符替换后一定能令整个字符串符合要求。

移入窗口:当前字符数量减1
移出窗口:窗口外字符都小于等于l/4时,缩小窗口看看还行不行,把左端字符加上
更新答案:窗口外字符都小于等于l/4时,统计答案,取min

代码如下:

class Solution {
public:int balancedString(string s) {int l = s.size();int n = l / 4;  //算1/4长度 unordered_map<char, int> m;//每种字符数量int ant = l;//答案,初始化为最大值for (char i : s)m[i]++;//遍历,统计一下字符串每个字符有多少个if (c['Q'] == n && c['W'] == n && c['E'] == n && c['R'] == n)return 0;//如果已经满足了直接返回for (int i = 0, j = 0; i < l; i++) {--c[s[i]];//移入窗口,窗口外字符--while (j <= i && c['Q'] <= n && c['W'] <= n && c['E'] <= n && c['R'] <= n) {//窗口外字符少于l/4ant = min(ant, i - j + 1);//更新答案++c[s[j]];//移出窗口,窗口外字符++j++;}}return ant;}
};

这道题我们需要考虑窗口外的性质,这又是一种处理方式。

map有时可以用普通数组替换,但这里为了让大家更好掌握滑动窗口的套路,我则都采用了map

992. K 个不同整数的子数组

这道题看起来没什么思路,如何处理k,我们想一下如果用滑窗处理k的话不成立,因为是否移出窗口不好处理,如果当前窗口大于k我们移出左端直到等于k,但这是再移出左端也有可能还等于k,如果又移动,则刚才的结果丢了,所以比较麻烦,但是如果我们算当前个数小于等于k是没问题的,如果窗口长为n,则答案可以加上n,表示包含最右端的子数组个数有K个。

我们只需算两遍,小于等于k与小于等于k-1的答案再做差即可。

移入窗口:当前数字放入窗口
移出窗口:如果种类多了,则移出左端
更新答案:加上以该元素为尾元素的符合要求的数组的数量

代码如下:

class Solution {
public:int subarraysWithKDistinct(vector<int>& nums, int k) {return f(nums, k) - f(nums, k - 1);//做差}int f(vector<int>& nums, int k) {unordered_map<int, int> m;//每种数字有多少个int n = nums.size();int ant = 0;//答案for (int i = 0, j = 0; i < n; i++) {m[nums[i]]++;//移入窗口while (j <= i && m.size() > k) {//数目多了减少if (--m[nums[j]] == 0) //移出窗口m.erase(nums[j]);j++;}ant += i - j + 1;//以i为最后元素的子数组有多少个}return ant;}
};

这道题思路较为巧妙,也是解题的难点

395. 至少有 K 个重复字符的最长子串

这道题也不好想思路,但是我们发现只有小写字母,也就是26个,那么我们可以循环遍历,当子串只有1,2,3......26种字符时,有无符合题意得子串。

移入窗口:当前字符数量加1
移出窗口:当字符种类超过当前循环要求时,移出左端
更新答案:检查窗口内每个字符是否符合要求,符合就更新为更长得长度

代码如下:

class Solution {
public:int longestSubstring(string s, int k) {unordered_map<char, int> m;//统计每种字符数量int n = s.size();int ant = 0;//答案for (int num = 1; num <= 26; num++) {m.clear();//清空,当窗口内有num种字符for (int i = 0, j = 0; i < n; i++) {m[s[i]]++;//移入窗口while (j <= i && m.size() > num) {if (--m[s[j]] == 0)//移出窗口m.erase(s[j]);j++;}if ( check(m, k) )//符合要求,更新答案ant = max(ant, i - j + 1);}}return ant;}bool check(unordered_map<char, int>& m, int k) {for (auto i = m.begin(); i != m.end(); i++)if (i->second < k)//遍历,看看每种字符数量是否符合题意return 0;return 1;}
};

这题难点在于思想,没有只用一次遍历得出答案,而是多次。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

重大喜讯!科研界之大变革——“5分钟提交+24小时反馈”,投稿效率直线上升!

盘点允许“一稿多投”的SCI “一稿多投”一直被认为是学术不端的行为&#xff0c;但“禁止一稿多投”是纸质时代遗留下的产物&#xff0c;已不符合当今社会的发展。 一篇文章一审就是好几个月甚至是一两年&#xff0c;在科研圈子里都是平常事&#xff0c;每个科研人都曾深陷于…

乐道L60、MONA M03、理想L6,蔚小理围剿「特斯拉」

作者 |老缅 编辑 |德新 9月19日&#xff0c;蔚来全新品牌乐道首款车型——乐道L60正式上市&#xff0c;定位家庭智能电动SUV。 60kWh标准续航版&#xff0c;售价20.69万元85kWh长续航版&#xff0c;售价23.59万元&#xff1b;如果采用BaaS电池租用服务&#xff0c;则低至14.9…

如何在云端使用 Browserless 进行网页抓取?

云浏览器是什么&#xff1f; 云浏览器是一种基于云的组合&#xff0c;它将网页浏览器应用程序与一个虚拟化的容器相结合&#xff0c;实现了远程浏览器隔离的概念。开发人员可以使用流行的工具&#xff08;如 Playwright 和​ Puppeteer​&#xff09;来自动化网页浏览器&#…

cmake--list

教程 list--链接 list关键字的作用 list的操作 list追加字符串--APPEND set(str1 "aaaaaaaa") message(STATUS "str1${str1}") list(APPEND str1 "bbbb") message(STATUS "str1${str1}") list字符串拼接并不是直接拼接&#xff0c…

C# 用Timer控件简单写一个倒计时60s功能

先放界面上一个Label和一个Timer控件&#xff0c;Label用来展示倒计时秒数 添加事件 设置属性&#xff0c;设置每隔一秒执行一次 放代码&#xff1a; //设置时间控件开始运行&#xff0c;具体放在哪里看具体需求 this.timer1.Start();//定义一个全局变量表示秒数 int time…

在线版宣传册是如何制作的

​亲爱的创作者们&#xff0c;你是否想过将传统的纸质宣传册升级为更具吸引力的在线版&#xff1f;在这个数字化时代&#xff0c;在线版宣传册不仅能够节省印刷成本&#xff0c;还能让信息传递更加迅速、精准。今天&#xff0c;就让我们一起探索在线版宣传册的制作奥秘吧&#…

利用Mongoose库实现MQTT通信

Mongoose官方Github地址 官方对于Mongoose的简介&#xff1a; Mongoose - Embedded Web Server / Embedded Network Library Mongoose is a network library for C/C. It provides event-driven non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocol…

【吉林一号卫星简介】

吉林一号卫星 吉林一号卫星是中国长光卫星技术有限公司研制的遥感卫星&#xff0c;也是该公司在建的核心工程&#xff0c;是中国重要的光学遥感卫星星座。以下是对吉林一号卫星的详细介绍&#xff1a; 一、卫星概况 中文名&#xff1a;吉林一号外文名&#xff1a;Jilin 1 Bus…

视频汇聚EasyCVR视频监控平台调取接口提示“认证过期”是什么原因?

视频汇聚EasyCVR视频监控平台&#xff0c;作为一款智能视频监控综合管理平台&#xff0c;凭借其强大的视频融合汇聚能力和灵活的视频能力&#xff0c;在各行各业的应用中发挥着越来越重要的作用。EasyCVR平台具备强大的拓展性和灵活性&#xff0c;支持多种视频流的外部分发&…

丝杆支撑座许用条件的解析

丝杆支撑座连接滚珠丝杆使用能够支撑滚珠丝杆&#xff0c;使之更加平稳的运动&#xff0c;显著提高传动效率、降低噪音、提高精度、延长使用寿命等优势&#xff0c;是自动化设备中重要的传动元件。影响丝杆支撑座的因素主要包括轴承类型、润滑脂的使用、密封圈的保护、使用环境…

实现边框渐变效果

实现思路&#xff1a;定义一个具有相对定位、白色背景和透明边框的元素。边框宽度为3像素&#xff0c;并且有20像素的圆角。通过background-clip: padding-box;确保背景不会延伸到边框之外。 使用一个伪元素&::before来创建一个渐变边框。这个伪元素被放置在主元素的外部&…

Qt-QComboBox输入类控件(31)

目录 描述 核心方法 核心信号 使用 代码方式 界面操作方式 动态使用 如何看待输入输出 String与QString互相转化 描述 一个可以下拉的输入框 核心方法 addItem(constQString&)添加⼀个条⽬currentIndex()获取当前条⽬的下标 从0开始计算.如果当前没有条⽬被选中…

Xcode 16 上传AppStore遇到第三方库 bitcode 的问题

Xcode 16 上传AppStore遇到第三方库 bitcode 的问题 最近两天更新了Xcode 16&#xff0c;然后正好要发布新版本的App&#xff0c;打包Adhoc没问题&#xff0c;但是上传AppStoreConnect或者TestFlight就不行解决方案参考资料 最近两天更新了Xcode 16&#xff0c;然后正好要发布新…

RegNet(CVPR2020):Designing Network Design Spaces,设计一个网络设计空间!

RegNet&#xff1a;Designing Network Design Spaces RegNet&#xff1a;设计一个网络设计空间 论文地址&#xff1a; https://arxiv.org/pdf/2003.13678 1、前言 在这项工作中&#xff0c;作者提出了一种新的网络设计范例。 作者的目标是帮助增进对网络设计的理解并发现跨设置…

【js逆向学习】酷我音乐排行榜 python+nodejs(webpack)

逆向目标 目标网址: https://www.kuwo.cn/rankList目标接口: https://www.kuwo.cn/api/www/bang/bang/musicList 加密参数: 参数一&#xff1a;secret参数二&#xff1a;reqId 逆向过程 老规矩先分析网络请求&#xff0c;我们可以分析到网络请求是通过ajax进行的&#xff…

【研赛E题成品论文】24华为杯数学建模研赛E题成品论文+可运行代码丨免费分享

2024华为杯研究生数学建模竞赛E题成品论文已出&#xff01; E题 高速公路应急车道紧急启用模型 一、问题一模型建立与求解 1.1 问题一求解思路 赛题要求我们基于四个观测点的视频数据&#xff0c;提取交通流参数并分析这些参数随时间的变化规律。交通流参数包括&#xff1a;…

JAVA并发编程系列(11)线程池底层原理架构剖析

面试官&#xff1a;说说JAVA线程池的几个核心参数&#xff1f; 之前我们用了10篇文章详细剖析了synchronized、volatile、CAS、AQS、ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier、并发锁、Condition等各个核心基础原理&#xff0c;今天开始我们说说并发领域的各种…

ChatGLM-6B:部署指南与实战应用全解析

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 SD3ComfyUI文生图部署步骤DAMODEL-ChatGLM-6B 服务端部署1.1、实例创建1.2、模型准备1.3、模型启动 SD3ComfyUI文生图部署步骤 Chat…

Redis6.0.9配置redis集群

写在前面 最近在完成暑期大作业&#xff0c;期间要将项目部署在云服务器上&#xff0c;其中需要进行缓存的配置&#xff0c;决定使用Redis&#xff0c;为了使系统更加健壮&#xff0c;选择配置Redis-Cluster。由于服务器资源有限&#xff0c;在一台服务器上运行6个Redis Instan…

pnpm : 无法加载文件

1、以管理员身份运行window powershell 2、执行Get-ExecutionPolicy&#xff0c;显示Restricted 3、执行set-ExecutionPolicy&#xff0c;会提示输入参数&#xff0c;此时输入RemoteSigned回车 4、执行y回车