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

定长滑动窗口和不定长滑动窗口

定长滑动窗口,题目一般会给我们长度为k

1.那么我们1先计算[0~k)第一个窗口里面的满足条件的

2.从i=k开始向右滑动窗口for(int i = k;i<n;i++);

这里我们算的是下标i从0往右移动逐渐循环每次遍历右边的k-1个数,

再判断窗口内的左边界[i-k],右边界[i]这两个数,因为我们移除的是左边的加入的是右边的,如果左边的满足条件,那满足条件而计算的一些贡献结果就要减掉,右边的满足条件贡献就要加上,

不用像暴力算法那样每次都要全部判断遍历整个窗口,提高效率

有时候也会需要使用到哈希表。

整数数组中长度为k的数组中所有的元素各不相同。(当题目要求:长度为 k 的子数组中所有元素互不相同)

需要结合滑动窗口和哈希表,unordered_map<数组元素类型,int>=cnt;

cnt<key>=val;key出现的次数,计算出现的次数和出现的元素,用哈希表计数可以快速判断窗口内是否有重复元素

哈希map = 计数+判重复

class Solution { public: long long maximumSubarraySum(vector<int>& nums, int k) { int n = nums.size(); long long current_sum = 0; long long max_sum = 0; unordered_map<int, int> cnt; // cnt[kay]=val;数字key出现的次数 long long unique_num = 0; for (int i = 0; i < k; i++) { if (cnt[nums[i]] == 0) { //如果之前没出现过,说明是新的唯一元素,unique_num 才会 +1。 unique_num++; } cnt[nums[i]]++;//把当前元素 nums[i] 加入哈希表,它的出现次数 +1 current_sum += nums[i]; if (unique_num == k) { max_sum = current_sum; } } for (int i = k; i < n; i++) { cnt[nums[i - k]]--; if (cnt[nums[i - k]] == 0) unique_num--; current_sum -= nums[i - k]; if (cnt[nums[i]] == 0) unique_num++; cnt[nums[i]]++; current_sum += nums[i]; if (unique_num == k) { max_sum = max(max_sum, current_sum); } } return max_sum; } };

不定长窗口(最长无重复子串)

必须使用set+双指针(left,right)

开始时left和right都是在数组下标为0的位置,但是left指针是不会动的,动的是右指针right。

right++,一直没有重复的数的时候就一直right++,出现重复时,left++,

class Solution { public: int lengthOfLongestSubstring(string s) { int n = s.size(); //两个指针,一开始都在最左边,然后右边的指针往右移动,左边的先不动,如果右边遇到重复的左边的再动 unordered_set<char>ooc; int max_len=0; int left = 0; for(int right=0;right<n;right++) { while(ooc.count(s[right])){ ooc.erase(s[left]); left++; }ooc.insert(s[right]); max_len=max(max_len,right-left+1); } return max_len; } };

不定长滑动窗口也会用到哈希map,这时候就要结合使用哈希map和left,right指针

1. 判断哈希表中键的数量 while(cnt.size() > ....) //限制种类

2. 判断哈希表中值的数量 while( cnt[x] >1 );//无重复的判断

这里是针对题目给的数组有具体的数字要求

3. 去除某个数值 cnt.erase(数组名[下标]);

数量变为0时删掉他,保证不影响cnt,size(), if (cnt[...] == 0) cnt.erase(...);

4. 判断是否会有重复 while(cnt[数组名[数组下标]] > 1){}

//一般是用下标判断

1和4的逻辑是一样的

class Solution { public: int totalFruit(vector<int>& fruits) { int n = fruits.size(); int left = 0; int max_num = 0; unordered_map<int, int>cnt; for (int right = 0; right < n; right++) { cnt[fruits[right]]++;//这里直接加就好了 current_num++; while (cnt.size() > 2)//判断哈希表中键的数量 { cnt[fruits[left]]--; if (cnt[fruits[left]] == 0)//彻底减为0时再去除,不然会影响 { cnt.erase(fruits[left]); } left++;//左指针再向右移 } max_num = max(max_num, right - left + 1); } return max_num; } };

含有若干不同元素

while(cnt[nums[right]]>1) { cnt[nums[left]]--; current_sum-=nums[left]; if(cnt[nums[left]]==0){ cnt.erase(nums[left]); } left++; }

这里是一个数组中所有元素的频率都小于等于k

class Solution { public: int maxSubarrayLength(vector<int>& nums, int k) { int n = nums.size(); int left=0; int max_len =0; unordered_map<int,int>cnt; for(int right=0;right< n;right++) { cnt[nums[right]]++; while(cnt[nums[right]]>k)//k { cnt[nums[left]]--; if(cnt[nums[left]]==0) { cnt.erase(nums[left]); } left++; } max_len=max(max_len, right-left+1); } return max_len; } };

当窗口收缩到刚好不满足条件时
left 的值 = 以 right 结尾的合法子串数量
所以直接 count += left

求最多、不超过、完全合法
→ += right - left + 1
求至少包含、必须都有
→ += left

class Solution { public: int beautifulBouquet(vector<int>& flowers, int cnt) { int n = flowers.size(); int count=0; int left=0; unordered_map<int,int>c; for(int right=0;right<n;right++) { c[flowers[right]]++; while(c[flowers[right]]>cnt)//右指针元素出现的次数>cnt { c[flowers[left]]--; left++; } count+=right-left+1; } return count; } };
class Solution { public: int numberOfSubstrings(string s) { int n = s.size(); int count = 0; int left = 0; int a_num = 0; int b_num = 0; int c_num = 0; for (int right = 0; right < n; right++) { if (s[right] == 'a') { a_num++; } else if (s[right] == 'b') { b_num++; } else if (s[right] == 'c') { c_num++; } while (a_num >= 1 && b_num >= 1 && c_num >= 1) { if (s[left] == 'a') { a_num--; } else if (s[left] == 'b') { b_num--; } else if (s[left] == 'c') { c_num--; } left++; } count += left; } return count; } };
http://www.cnnetsun.cn/news/1494566.html

相关文章:

  • AI Agent大爆发!从“会聊天“到“能办事“,大厂布局全景解析,普通人如何抢占先机?
  • 突破跨平台文件处理瓶颈:dmg2img的跨平台解决方案实战指南——写给开发者与运维人员的格式转换完全手册
  • SpringCloud
  • Win11Debloat:Windows系统优化的模块化解决方案与技术实践
  • 动画设置、自定义放映、幻灯片放映设置、排练计时
  • 别再手动标点了!用Python解析无人机JPG照片,自动获取图上任意点的GPS坐标
  • 工业数据智能:从混沌到秩序的底层重构
  • 程序人生之知幻即离,离幻即觉:《圆觉经》智慧给职场工作的深层启发
  • 从零开始:mitmproxy跨平台证书配置与实战抓包指南
  • 如何快速掌握免费UML绘图工具:UMLet新手完全指南
  • 你也想转行网安吗?作为过来人的我希望你想清楚这几个问题再做决定
  • KindEditor富文本编辑器:轻量级网页内容创作解决方案
  • 保姆级教程:用LTspice仿真带你搞懂USB3.2信号上的AC耦合电容,容量与封装到底怎么选
  • 基于RetinaFace的实时视频会议系统:人脸追踪与虚拟背景
  • 别再手动建模了!用SolidWorks导出的STL模型,在MATLAB里5分钟搞定静力学仿真
  • 5个颠覆级技巧:用Fastboot Enhance实现Android设备安全高效管理
  • 5步玩转OpenDroneMap:从图像到三维模型的全流程指南
  • 深度学习入门神器:PyTorch 2.6 镜像快速部署教程,开箱即用免配置
  • 基于LaravelS与Swoole构建高并发WebSocket实时通信服务
  • Win11Debloat:Windows 11终极优化工具完整指南
  • 3个步骤打造你的智能笔记助手:obsidian-copilot从安装到精通
  • 飞书文档智能备份终极指南:3步实现企业知识库全自动同步
  • Qwen1.5-1.8B GPTQ生成技术博客大纲与初稿:以“操作系统内存管理”为例
  • 数字工具如何让手写艺术重获新生?
  • 别再手动算坐标了!UE5蓝图UI的Menu Anchor,5分钟搞定浮动详情弹窗
  • 税务季网络钓鱼攻击的演进特征、社会工程学机制与多维防御体系构建
  • DamoFD人脸检测模型实战教程:5步完成关键点检测部署
  • Halcon圆弧检测避坑指南:为什么你的拟合圆总是不准?
  • 如何安全获取安卓应用?APKMirror带来的革新性解决方案
  • Windows搭建WebDAV服务:从内网穿透到本地盘符映射的完整指南