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

滑动窗口算法专题+题目详解

1.⻓度最⼩的⼦数组

目录

1.⻓度最⼩的⼦数组

2.⽆重复字符的最⻓⼦串

3. 最大连续 1 的个数 III

4.将 x 减到 0 的最⼩操作数

5.找出字符串中所有字母异位词

6.水果成篮


滑动窗口的本质就是同向双指针,它也有一个固定的模板,分为进窗口,判断,出窗口,然后再特定的位置更新结果.

解法思路:本题我们使用滑动窗口来解决问题,滑动窗口本质上就是同向的双指针。我们来分析题目,求最短的子数组之和满足大于等于target。我们观察,我们首先定义letf = 0,right = 0 ,将开头定在最左边,right也定义在最左边,然后移动right,求left到right之间的数组之和,当他们之间的和大于等于target的时候,这时的长度有可能时最短长度,所以我们需要与上次(我们定义一开始的最短长度为 INT_MAX)的长度所比较,如果比上一次的短,那么我们就需要更新最短长度。此时我们的left和right之间的数组之和是满足题目要求的,如果我们继续让rihgt++ ,只会是数组更大 ,长度更长,似乎没意义,所以我们需要缩短left和rihgt之间的差距,就要让left++,再次观察left和right之间的数组之和是否满足题目要求。满足我们就可以更新最小长度,如果不满足我们就让rihgt++,如此循环便可以得到最短的长度,这就像一扇窗户一样,在不停的拉开,和关上

代码示例:

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int ret = INT_MAX; //定义初始的最小值是INT_MAX 保证第一次比较会改变长度的值int left = 0,right = 0;int sum = 0;while(left<=right && right<nums.size()){sum+=nums[right];while(sum>=target)//  当满足条件时,就跟新长度{ret = min(ret,right-left+1);sum-=nums[left++];}right++;}return ret==INT_MAX ? 0 : ret;}
};

2.⽆重复字符的最⻓⼦串

解题思路:

这道题如果用暴力解法的话,就是一个双循环,就可以找到最长的数组,但是这道题目用双循环会超时,所以我们想一下优化的解法,就是滑动窗口。

我们首先定义一个left,和一个right指向字符串的开头,然后让right++,直到right指向重复的字符,我们为了方便可以利用hash表来记录字符出现的次数,当在hash表中有字符出现两次时,我们就需要移动left,并且将left所对应的字符从hash表中去除,也就是出窗口,直到left移动到重复字符的后面,hash表中right所对应的字符就只出现了一次,这是也就说明又没有重复字符了,我们就继续移动right。然后更新最长的长度。

代码示例:

class Solution {
public:int lengthOfLongestSubstring(string s) {int hash[128] = {0}; //定义一个仿hash表int left = 0,right = 0; int ret = 0;while(right<s.size()) //结束条件right到达结尾{hash[s[right]]++;  // 将right所对应的字符对应到hash表中,并且将次数加1;while(hash[s[right]]>1)  // 当right所对应的字符出现两次,就需要出窗口了{hash[s[left++]]--; // 出窗口操作,将left所对应的字符在hash表中去除,直到left            //移动到重复字符的后面,此时重复的元素的次数就减去一次,我//们就可以重新开始寻找没有重复字符的最长字串了}ret = max(ret,right-left+1); //更新最大值right++;// 让right继续下去;}return ret;}
};

3. 最大连续 1 的个数 III

解法思路:

不要把这个题目想复杂,可以反转k个整数,不就是在一个全是1的数组中可以有多少了0吗?这样就可以把问题化简。

我们利用滑动窗口算法,定义一个left和一个right指向数据开头,我们可以利用一个计数器count来记录0出现的次数,让right向后移动遇到0的时候就让count++,知道count的值大于k时,我们就需要让left++,然后进行判断,如果left对应是1,就继续让left++,当遇到0时,就让count--,直到count小于等于k,然后更新返回的结果

代码示例:

class Solution {
public:int longestOnes(vector<int>& nums, int k) {int count = 0;//计数器int ret = 0;           //返回值int left =0 ,right = 0; // 左右指针while(right<nums.size()) {   if(nums[right]==0) // 当right==0 ,计数器++count++;while(count>k) // 判断,当count>k时,就需要让left向右移,直到count小于等于k{if(nums[left]==0){count--;                    }left++;}ret = max(ret,right-left+1);//更新返回值right++;//右边的指针++;}return ret;}
};

4.将 x 减到 0 的最⼩操作数

解题思路:

这道题目我们发现按照题目的要求这么取做的话,我们用肉眼发现是很简单的,但是代码描述却是十分的复杂,所以我们“正难则反”,我们观察发现这道题目可以变为求最长子数组,使得这个子数组之和等于数组之和(Sum)减去x。当这个子数组最长,并且子数组之和时Sum-x;那么这正好时去除了两边最少的个数并且满足相减为0;这样就简单了,详细解释在代码中

代码示例:

class Solution {
public:int minOperations(vector<int>& nums, int x) {int n  = nums.size(),Sum = 0;// 将数组长度赋给n,定义Sum记录数组之和for(auto e: nums)//求数组所有元素之和{Sum+=e;}int target = Sum - x;// 将Sum-x就是子数组需要满足的条件 定义为targetint len = -1;// 起始长个数为-1;int left = 0, right = 0; // 利用滑动窗口 int sum = 0;// 这个sum是用来求子数组之和的if(target<0) //特殊情况:当target<0 也就是整个数组之和都没有x大,那么不存在可以满足的                                    return -1;  //条件,直接返回-1;while(right<n) // 开始遍历数组{ sum+=nums[right]; // 将right指向的元素加入sum,求left到right之间子数组的和while(sum>target)//判断 当sum > target时,说明数组已经过长,并且在left和right之                                                            //间不存在满足的子数组,让right继续向后走没有意义;{                //所以更新一下子数组,从sum中减去left所指元素,让left++; 这样// 子数组的个数就更新了sum-=nums[left++];}if(sum==target)//只有当出现sum等于targer时,才能满足条件,然后更新结果{len = max(len,right-left+1);//记录下最长数组长度}right++;}//注意,返回值时,我们求的时最长的子数组但是题目要求时最小的操作次数,所以我们返回值            //时,需要用数组长度减去最长子数组长度if(len == -1)return -1;elsereturn n-len;}
};

5.找出字符串中所有字母异位词

  这道题目最简单是通过滑动指针和hash表来实现,直接开始题目解析

题目解析:

 题目中要求我们找出所有关于p的异位词,异位词就是指p中的所有字符随机组合成的一个新的字符串,我们在这提出一个思路,既然是异位词,那么就包含p中的所有字母,那我们就将题目转化为在s字符串中找到一个子字符串,这个子字符串中的字符数量和字符种类要和p中的要相同就可以了,这样我们就将题目变简单了

详细解释在代码中解释

class Solution {
public:vector<int> findAnagrams(string s, string p) {int count = 0//用于计算在窗口中的有效字符数int hash1[26]={0};//记录p中的对应字符数量vector<int> ret;//返回的数组int hash2[26]={0};// 记录在窗口中的对应字符数量for(auto e: p) //将p中的所有字符和数量记录在hash1中{hash1[e-'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']) //如hash1中的对应字符数量大于hash2中的对应字                               //数(因为是先进了窗口,所以要加上等于),如何是         // 一个无效字符,他一定不在hash1中,所以我们就 //不需要将有效位数量count++,他在最后出窗口时也 //一定会被出掉的{count++;//有效字符就加1,}          if(right - left +1 > p.size())  //判断  当right和left之间的值大于p的数量时,就                ////代表窗口中的元素过多,需要出窗口                                                                                        {char out = s[left]; //待出窗口元素if(hash2[out-'a'] <= hash1[out-'a']) //出窗口 当待出窗口元素数量小于等于                                                              //hash1中的元素时我们就要将该元素从有        //效字符数量中减去,然后出窗口count--;hash2[out-'a']--;left++;}if(count==p.size()) //当此时我们的有效字符数量和p的字符数量相等的时候,说                                                                    //明我们找到了一个异位词,将起始位置left翻入ret中{ret.push_back(left);}}return ret;}
};

6.水果成篮

题目解析:

       我们经过读题可以发现,题目要求我们的两个篮子里中的每个篮子的水果种类要是相同的,也就是我们所能采摘的水果只能是两种,所以我们就将题目转化为了在一个数组中,只有两种数字的最大长度,显然,这题的解题思路还是滑动窗口

代码示例:

class Solution {
public:int totalFruit(vector<int>& fruits) {unordered_map<int,int> hash;//用一个hash表来记录种类和数量int ret = 0;for(int left = 0,right =0 ;right<fruits.size();right++){hash[fruits[right]]++;//进窗口  将该种类放入hash表中if(hash.size()>2)//判断如果种类大于两种了,就需要出窗口{  while(hash[fruits[left]] >1) //如果当前品种的数量大于1,我们就需要将他减去,并 //且将他从窗口里出掉{hash[fruits[left]]--;//减去一个数量left++;//出窗口}hash.erase(fruits[left]);//到这里的时候,种类数量还多余两个,此时left所指向     //的种类的个数一定只剩一个了,所以我们需要将他从        ////hash表中去除left++;}ret = max(right-left+1,ret);//更新结果}return ret;}
};

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

相关文章:

  • 数据中心双供电架构中的智能化切换与预警管理
  • 网站图片怎么做优化济南网络营销网站建设
  • 各种各样的Self-attention学习下(第二十一周周报)
  • 网站前台功能模块介绍郑州网站建设一汉狮网络
  • 网站开发服务 税社交系统开发
  • 简单聊一下vue中的#app
  • 网站空间支持下载但不能下载文件简单门户网站开发
  • 厦门市小学生信息学竞赛(C++)初赛总复习(第二章 算法知识与数据结构 -第四节 队列)
  • 化工类网站建设推广网站备案后下一步做什么
  • 做网站一般需要哪些文件夹?兰州网站开发公司
  • 获取 Excel 工作表的名字【Java 图文详解】
  • 邢台专业做网站贝斯特专业网站
  • 惠州网站建设公司上海企业宣传片制作
  • 网站 建设文档提供邢台专业做网站
  • Gradle Groovy 和 Kotlin kts 语法对比
  • 做网站维护有什么要求物联网开发软件有哪些
  • 普陀做网站特色的岑溪网站开发
  • 对重庆电子政务网站建设评价wordpress模板里写php
  • 企业网站的网络营销功能包括还没做域名解析如何访问ftp的网站文件
  • 免费开网站自己家的电脑做网站需要备案没
  • 心理咨询网站后台学设计常用的网站
  • 安卓开发学习10-中级控件
  • 公司网站升级改版方案wordpress 一级目录
  • Rust 日志级别与结构化日志:从调试到生产的日志策略
  • 建英文网站有用吗自动外链发布工具
  • 从BSP到DFP和RTOS---专业的嵌入式开发工具Keil备忘
  • 【SpringBoot从初学者到专家的成长25】认识SpringBoot中的Spring Expression Language (SpEL)
  • IntelliJ IDEA配置Tomcat教程
  • 北京做网站建设的公司排名网页qq登陆保护在哪里
  • 广东省网站集约化建设做外贸如何建立网站