算法:滑动窗口解决连续区间子数组问题

文章目录

  • 实现原理
  • 实现思路
  • 典型例题
    • 长度最小的子数组
    • 无重复字符的最小字串
    • 最大连续1的个数III
    • 将x减到0的最小操作
    • 水果成篮
    • 找到字符串中所有字母异位词(哈希表比较优化)
      • 对哈希表内元素比较的优化
  • 总结

本篇积累的是滑动窗口的问题,滑动窗口在算法实现中有重要作用,可以解决很多问题

实现原理

当遇到需要在题目中寻找一个符合条件的子数组时,或在一段区间内寻找一段连续的区间时,就可以用到这种算法,这个算法的原理就是用左右指针形成一个区间,这个区间用以寻找满足条件的区间

实现思路

具体的实现思路要依托于单调性从而进行同向双指针的优化

这里的单调性并非指的是数据顺序的递增或递减,而是说随着窗口的变大变小或滑动,窗口内数据的整体变化趋势,因此对于一些全为正数的数据量来说,滑动窗口是比较契合解决问题的

那么具体的使用就是定义两个指针,leftright,这两个指针用来作为窗口的左右窗框,这段区间中间的部分就是窗口

既然叫做滑动窗口,那么必然这两个指针是要动起来的,right就是所谓的进窗口,再进行判断是否需要出窗口,再更新结果即可


典型例题

长度最小的子数组

在这里插入图片描述

从此题中,其实可以看出滑动窗口是有其大体思路的,简单总结就是进窗口,判断,出窗口,代码形式多样,但核心思路不变,关键在于寻找while循环的条件,也就是出窗口部分的条件是什么

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

无重复字符的最小字串

在这里插入图片描述

此题的关键思路是找不重复的字串,如果重复就要寻找下一个,那么核心思路不变,依旧是进窗口,判断,出窗口,问题核心关键在于while循环,这里涉及到如果有重复元素在字串中就停止进窗口,因此可以借助一个哈希表来检测是否有重复元素,因此在这里创建一个数组哈希表即可

当检测到元素含有重复元素时,就进行出窗口,出窗口一直出到整个窗口中不含有该重复元素,使得可以继续进窗口找不重复序列

class Solution 
{
public:int lengthOfLongestSubstring(string s) {int left=0,right=0,hash[128]={0},ret=0;for(left=0,right=0;right<s.size();right++){// 进窗口hash[s[right]]++;// 判断while(hash[s[right]]>1){// 出窗口hash[s[left++]]--;}ret=max(ret,right-left+1);}return ret;}
};

最大连续1的个数III

在这里插入图片描述

对于此题来说,如果直观去考虑,要按照题意反转数字再进行统计会相当麻烦,因此这里换一种思路进行问题解决

比如,这里可以把题意转换为,使得区间内的0的个数小于K

基于这样的考虑,就可以使用滑动窗口了,整体来看和前面的思维一样,只是需要有一个思维的转换,基于这样的情况下,代码实现并不困难

class Solution 
{
public:int longestOnes(vector<int>& nums, int k) {int left=0,right=0,len=0,ret=0;for(left=0,right=0;right<nums.size();right++){// 进窗口if(nums[right]==0){ret++;}// 判断if(ret>k){// 出窗口while(nums[left++]!=0);ret--;}len=max(len,right-left+1);}return len;}
};

由此可见,滑动窗口就是三部曲 进窗口,判断,出窗口
掌握整个原理即可应对滑动窗口的问题

将x减到0的最小操作

在这里插入图片描述

本题用到了一个正难则反的思想,把问题转换为求中间部分的最大值即可,这里要注意对于如果中间没有找到内容要进行记录的问题,并且要一直找下去,要注意更新数据的位置

class Solution 
{
public:int minOperations(vector<int>& nums, int x) {int sum=0;for(int i=0;i<nums.size();i++){sum+=nums[i];}int tmp=sum-x;if(tmp<0){return -1;}int left=0,right=0,len=-1,ret=0;for(int left=0,right=0; right<nums.size();right++){// 进窗口ret+=nums[right];// 判断while(ret>tmp){// 出窗口ret-=nums[left];left++;}if(ret==tmp){len=max(len,right-left+1);}}return len==-1? len:(nums.size()-len);}
};

水果成篮

在这里插入图片描述

class Solution 
{
public:int totalFruit(vector<int>& fruits){int hash[100001] = { 0 }, kind = 0, len = 0;for (int left = 0, right = 0; right < fruits.size(); right++){// 进窗口if (hash[fruits[right]] == 0){kind++;}hash[fruits[right]]++;// 判断while (kind > 2){// 出窗口hash[fruits[left]]--;if (hash[fruits[left]] == 0){kind--;}left++;}len = max(len, right - left + 1);}return len;}
};

找到字符串中所有字母异位词(哈希表比较优化)

在这里插入图片描述

本题也是滑动窗口的经典题目,和前面不同的是窗口长度是固定的,但整体上遵循进窗口,判断,出窗口的规则就可以解决,但这当中有些许步骤可以优化

先看正常方法如何进行代码编写

class Solution 
{
public:bool hashcmp(int a[], int b[], int sz){for (int i = 0; i < sz; i++){if (a[i] != b[i])return false;}return true;}vector<int> findAnagrams(string s, string p){vector<int> v;int hash1[26] = { 0 };int hash2[26] = { 0 };// p内数据扔到hash1中for (auto ch : p){hash1[ch - 'a']++;}for(int left=0,right=0;right<s.size();right++){// 进窗口char in=s[right];hash2[in-'a']++;// 判断if(right-left+1==p.size()){if(hashcmp(hash1,hash2,26)){v.push_back(left);}// 出窗口char out=s[left];hash2[out-'a']--;left++;}}return v;}
};

这里用数组模拟了两个哈希表,一个哈希表用来存储的是要找的子字符串的数据,另外一个哈希表内存的是滑动窗口内字符串的数据

这里有一个哈希表比较的问题,决定最终能否将left放到vector中的条件就是看这两个哈希表中的元素是否相同,如果相同就可以放到vector

但比较是个问题,对于这个题来说哈希表中我们只存放了26个字符,比较也只需要比较26次就可以得出结论,但如果这里存放的内容不仅仅是小写字母,还有其他字母?那此时这里再使用每一个元素进行遍历就显得很差,因此这里可以采取一些措施进行相应的优化

对哈希表内元素比较的优化

这个优化方法是采用一个count变量用以表示哈希表中有效字符的个数,假设这里采用的子字符串是abc

那么当入窗口是a的时候,此时哈希表中a的元素对应的数据是0,就可以入数据,此时这个a隶属于有效数据,可以入窗口,但如果要继续入数据a,此时子字符串对应的哈希表中字符a的数据量是1,而滑动窗口中对应的哈希表中字符a对应的数据量已经满足要求了,如果再入该数据则说明这个a是无效的数据,此时count就不进行增加

那么这个有什么用?count进行有效数据的维护和两个哈希表的比较有什么关系?

其实结论在于,在最后判断的时候,如果有效字符的数量和滑动窗口的长度相同,就恰恰说明了滑动窗口对应的哈希表中的数据和子字符串的哈希表中对应的数据是相同的,因此这两个哈希表就是相同的,也就达到了比较哈希表的目的

class Solution 
{
public:vector<int> findAnagrams(string s, string p){int count=0;vector<int> v;int hash1[26] = { 0 };int hash2[26] = { 0 };// p内数据扔到hash1中for (auto ch : p){hash1[ch - 'a']++;}for(int left=0,right=0;right<s.size();right++){// 进窗口char in=s[right];hash2[in-'a']++;if(hash2[in-'a']<=hash1[in-'a']){count++;}// 判断if(right-left+1>p.size()){// 出窗口char out=s[left];if(hash2[out-'a']<=hash1[out-'a']){count--;}hash2[out-'a']--;left++;}if(count==p.size()){v.push_back(left);}}return v;}
};

总结

滑动窗口其实本质可以作为是一种同向的双指针,主要需要遵循的步骤就是进窗口,判读,出窗口,只要找到合适的循环条件,解决问题并不困难

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

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

相关文章

自动驾驶仿真:基于Carsim开发的加速度请求模型

文章目录 前言一、加速度输出变量问题澄清二、配置Carsim动力学模型三、配置Carsim驾驶员模型四、添加VS Command代码五、Run Control联合仿真六、加速度模型效果验证 前言 1、自动驾驶行业中&#xff0c;算法端对于纵向控制的功能预留接口基本都是加速度&#xff0c;我们需要…

pandas数据分析40——读取 excel 合并单元格的表头

案例背景 真的很容易疯....上班的单位的表格都是不同的人做的&#xff0c;所以就会出现各种合并单元格的情况&#xff0c;要知道我们用pandas读取数据最怕合并单元格了&#xff0c;因为没规律...可能前几列没合并&#xff0c;后面几列又合并了....而且pandas对于索引很严格&am…

地球IT

地球是我们生活的家园&#xff0c;也是人类发展的基地。地球不仅仅是一个行星&#xff0c;更是一个复杂而有机的生态系统。 地球直径约为12,742公里&#xff0c;被称为“蓝色星球”&#xff0c;因为它的表面约70%被水覆盖。海洋是地球上最大的生态系统之一&#xff0c;它们扮演…

JavaScript对象知识总结

一、创建对象的三种方式 1、字面量创建对象 2、new关键字&#xff0b;构造函数创建对象 3、Object.create()创建对象 二、查看对象属性和更改对象值的两种方式 1、形如&#xff1a;obj.keyvalue 2、形如&#xff1a;obj[key]value 三、删除对象属性 1、delete obj.key …

计算机竞赛 图像检索算法

文章目录 1 前言2 图像检索介绍(1) 无监督图像检索(2) 有监督图像检索 3 图像检索步骤4 应用实例5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 图像检索算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff…

【数理知识】向量的坐标基表示法,Matlab 代码验证

序号内容1【数理知识】向量的坐标基表示法&#xff0c;Matlab 代码验证2【数理知识】向量与基的内积&#xff0c;Matlab 代码验证 文章目录 1. 向量的坐标基表示2. 二维平面向量举例3. Matlab 代码验证Ref 1. 向量的坐标基表示 假设空间中存在一个向量 a ⃗ \vec{a} a &#…

Vite更新依赖缓存失败,强制更新依赖缓存

使用vitets开发一段时间了&#xff0c;感觉并不是想象中的好用&#xff0c;特别是出现些稀奇古怪的问题不好解决&#xff0c;比如下面这个问题 上午9:50:08 [vite] error while updating dependencies: Error: ENOENT: no such file or directory, open E:/workspace-dir/node…

ansible(1)-- 部署ansible连接被控端

目录 一、部署ansible 1.1 安装 1.2 测试连接 192.168.136.55 ansible 192.168.136.56被控端 一、部署ansible 1.1 安装 zabbix-s只是主机名&#xff0c;不用在意&#xff0c;更好该主机也安装了zabbix&#xff0c;不好更改。 下载阿里云epel源 #安装阿里云的epel源&#…

计算机网络(9) --- 数据链路层与MAC帧

计算机网络&#xff08;8&#xff09; --- IP与IP协议_哈里沃克的博客-CSDN博客IP与IP协议https://blog.csdn.net/m0_63488627/article/details/132155460?spm1001.2014.3001.5502 目录 1.MAC帧 1.MAC地址 2.MAC帧报头 3.资源碰撞 4.MTU 1.对IP协议的影响 2.对UDP协议…

esp8266+电压检测模块检测电池电压

请注意 esp8266的ADC引脚受wifi模块影响&#xff0c;会导致不准确&#xff0c;具体请查看这里&#xff1a;https://github.com/esp8266/Arduino/issues/2070 简单说一下解决方案&#xff1a; ①如果不是频繁的读取数据&#xff0c;可以在wifi连接前读取数据然后存储到缓存&…

【Visual Studio Code】--- Win11 配置 VS Code 为中文 超详细

Win11 配置 VS Code 为中文 超详细 一、概述二、重要提示二、配置 VS Code 为中文 一、概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 二、重要提示…

RT-Thread 的环形缓冲区 ---- 镜像指示位

可以看一下这篇我写的博客&#xff0c;了解一下大概&#xff1a; RingBuffer 环形缓冲区----镜像指示位_呵呵哒(&#xffe3;▽&#xffe3;)"的博客-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/132340883?spm1001.2014.3001.5501 【回顾】缓冲区…

Mock平台-08开发:项目管理(四)编辑功能和Component抽离

【Mock平台】为系列测试开发教程&#xff0c;从0到1编码带你一步步使用Spring Boot 和 Antd React框架完成搭建一个测试工具平台&#xff0c;希望作为一个实战项目对各位的测试开发学习之路有帮助&#xff0c;大奇一个专注测试技术干货原创与分享的家伙。 本篇重点&#xff1a;…

MetaMask Mobile +Chrome DevTools 调试Web3应用教程

注&#xff1a;本教程来源网络&#xff0c;根据项目做的整理 写好了WEB3应用&#xff0c;在本地调试用得好好的&#xff0c;但是用钱包软件访问就报莫名的错&#xff0c;但是又不知道是什么原因&#xff0c;排查的过程非常浪费时间 。 因此在本地同一局域网进行调试就非常有必要…

mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除

写在前面&#xff1a; 本文主要介绍mybatis-plus的配置&#xff0c;以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql&#xff0c;这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…

​8th参考文献:[8]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022.

​&#xff18;th参考文献&#xff1a;&#xff3b;&#xff18;&#xff3d;许少辉&#xff0e;乡村振兴战略下传统村落文化旅游设计&#xff3b;&#xff2d;&#xff3d;北京&#xff1a;中国建筑出版传媒&#xff0c;&#xff12;&#xff10;&#xff12;&#xff12;&…

RK3588平台开发系列讲解(AI 篇)RKNN C API 详细说明

文章目录 一、API 硬件平台支持说明二、API 函数介绍2.1、rknn_init2.2、rknn_destroy2.3、rknn_query2.4、rknn_inputs_set2.5、rknn_run2.6、rknn_outputs_get2.7、rknn_outputs_release沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要讲解 RKNN C API 详细…

springboot 项目日志配置文件详解

spring boot 项目指定 日志配置文件 在Spring Boot项目中&#xff0c;可以通过在application.properties或application.yml文件中指定日志配置文件来配置日志。 1. 使用application.properties文件&#xff1a; 在application.properties中&#xff0c;您可以使用以下属性来…

【ARM】Day4 点亮LED灯

1. 思维导图 2. 自己编写代码实现三盏灯点亮 .text .global _start _start: /**********LED1&#xff0c;LED2,LED3点灯:PE10,PF10,PE8**************/ RCC_INIT:使能GPIOE组/GPIOF组控制器,通过RXCC_MP_AHB4ENSETR设置第[5:4]位写1,地址:0x50000A28[5:4]1ldr r0,0x50000A28 …

01_Redis单线程与多线程

01——Redis单线程与多线程 一、Redis是单线程还是多线程 在谈Redis的单线程或多线程时&#xff0c;需要根据版本来区分。 在redis 3.x之前&#xff0c;redis是单线程的从redis 4.x开始&#xff0c;redis引入多线程。处理客户端请求时&#xff0c;使用单线程&#xff1b;在异…