算法2--滑动窗口

滑动窗口

  • 滑动窗口
  • 经典例题
    • 长度最小的子数组
    • 无重复字符的最长子串
    • [最大连续1的个数 III](https://leetcode.cn/problems/max-consecutive-ones-iii/description/)
    • [将 x 减到 0 的最小操作数](https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/description/)
    • 水果成篮
    • 找到字符串中所有字母异位词
    • 串联所有单词的子串
    • 最小覆盖子串

滑动窗口

滑动窗口的本质就是同向双指针,而且两个指针都不回退,条件满足就可以让右指针右移使元素进入窗口,否则右移左指针使一些元素退出滑动窗口直至条件满足,由于左右指针都是只向右移动不回退,故其时间复杂度为O(n),适用于数组等可以下标随机访问的场景。

经典例题

长度最小的子数组

题目描述:
给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的子数组[numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int left=0;int right=0;vector<int> sums;int ans=INT_MAX;while(right<nums.size())    {int tmp=sums.size()?sums.back():0;sums.push_back(tmp+nums[right++]);if(sums.back()>=target){int l=left;int r=sums.size()-1;while(l<=r){if(ans>sums.size()){ans=sums.size();}int mid=(l+r)/2;if(sums.back()-sums[mid]>=target){left=mid+1;if(ans>right-left){ans=right-left;}l=mid+1;if(l>=r||sums.back()-sums[l]<target){break;}}else {r=mid-1;if(r>=0&&(sums.back()-sums[r]>=target)&&(ans>right-r)){ans=right-r-1;}}}}}if(INT_MAX==ans){return 0;}return ans;}
};
class Solution
{
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size(), sum = 0, len = INT_MAX;for(int left = 0, right = 0; right < n; right++){sum += nums[right]; // 进窗⼝while(sum >= target) // 判断{len = min(len, right - left + 1); // 更新结果sum -= nums[left++]; // 出窗⼝}}return len == INT_MAX ? 0 : len;}
};

无重复字符的最长子串

题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。

class Solution {
public:int lengthOfLongestSubstring(string s) {int len=0;int curLen=0;int left=0;int right=0;vector<int> counts(256,0);while(right<s.size()){if(1==counts[s[right]]){curLen=right-left;if(len<curLen){len=curLen;}counts[s[left++]]=0;}else{counts[s[right++]]=1;}}curLen=right-left;if(len<curLen){len=curLen;}return len;}
};
class Solution
{
public:int lengthOfLongestSubstring(string s) {int hash[128] = { 0 }; // 使⽤数组来模拟哈希表int left = 0, right = 0, n = s.size();int ret = 0;while(right < n){hash[s[right]]++; // 进⼊窗⼝while(hash[s[right]] > 1) // 判断hash[s[left++]]--; // 出窗⼝ret = max(ret, right - left + 1); // 更新结果right++; // 让下⼀个元素进⼊窗⼝}return ret;}
};

最大连续1的个数 III

题目描述:给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

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

将 x 减到 0 的最小操作数

题目描述:给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

class Solution {
public:int minOperations(vector<int>& nums, int x) {int len=INT_MAX;int left=0;int right=0;int sum=0;while(left<nums.size())    {if(left==right%nums.size()&&right>=nums.size()){break;}sum+=nums[right%nums.size()];while(sum>x&&left<nums.size()){sum-=nums[left++];}if(sum==x&&left<nums.size()){if(0==left||right+1>=nums.size()){len=min(len,right-left+1);}sum-=nums[left++];}++right;}return len==INT_MAX?-1:len;}
};
class Solution
{
public:int minOperations(vector<int>& nums, int x) {int sum = 0;for(int a : nums) sum += a;int target = sum - x;// 细节问题if(target < 0) return -1;int ret = -1;for(int left = 0, right = 0, tmp = 0; right < nums.size(); right++){tmp += nums[right]; // 进窗⼝while(tmp > target) // 判断tmp -= nums[left++]; // 出窗⼝if(tmp == target) // 更新结果ret = max(ret, right - left + 1);}if(ret == -1) return ret;else return nums.size() - ret;}
};

水果成篮

题目描述:你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

class Solution {
public:int totalFruit(vector<int>& fruits) {vector<vector<int>> backet(2,vector<int>(2,0));int maxSum=0;int left1=0;int left2=0;int cur=0;while(cur<fruits.size()){if(fruits[cur]!=fruits[0]){break;}++cur;}left1=cur-1;left2=cur;int right=cur;backet[0][0]=fruits[0];backet[0][1]=cur;if(cur<fruits.size()){backet[1][0]=fruits[cur];}while(right<fruits.size()){if(fruits[right]==backet[0][0]){++backet[0][1];left1=right;}else if(fruits[right]==backet[1][0]){++backet[1][1];left2=right;}else {if(maxSum<backet[0][1]+backet[1][1]){maxSum=backet[0][1]+backet[1][1];}if(left1<left2){backet[1][1]=left2-left1;backet[0][0]=fruits[right];backet[0][1]=1;left1=right;}else{backet[0][1]=left1-left2;backet[1][0]=fruits[right];backet[1][1]=1;left2=right;}}++right;   }if(maxSum<backet[0][1]+backet[1][1]){maxSum=backet[0][1]+backet[1][1];}return maxSum;}
};
class Solution
{
public:int totalFruit(vector<int>& f) {unordered_map<int, int> hash; // 统计窗⼝内出现了多少种⽔果int ret = 0;for(int left = 0, right = 0; right < f.size(); right++){hash[f[right]]++; // 进窗⼝while(hash.size() > 2) // 判断{// 出窗⼝hash[f[left]]--;if(hash[f[left]] == 0)hash.erase(f[left]);left++;}ret = max(ret, right - left + 1);}return ret;}
};

找到字符串中所有字母异位词

题目描述:给定两个字符串 s 和 p,找到 s 中所有 p 的
异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> originCount(128,-1);vector<int> curCount(128,0);int count=0;int i=0;for(;i<p.size();++i){if(-1==originCount[p[i]]){originCount[p[i]]=1;}else{originCount[p[i]]++;}}int left=0;int right=0;vector<int> ans;for(;right<s.size();++right){if(-1==originCount[s[right]]){curCount=vector<int>(128,0);left=right+1;count=0;}else{if(curCount[s[right]]<originCount[s[right]]){++curCount[s[right]];++count;}else{for(;left<right;++left){if(s[left]==s[right]){++left;break;}--count;curCount[s[left]]--;}}}if(count==p.size()){ans.push_back(left);}}return ans;}
};
class Solution
{
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26] = { 0 }; // 统计字符串 p 中每个字符出现的个数for(auto ch : p) hash1[ch - 'a']++;int hash2[26] = { 0 }; // 统计窗⼝⾥⾯的每⼀个字符出现的个数int m = p.size();for(int left = 0, right = 0, count = 0; right < s.size(); right++){char in = s[right];// 进窗⼝ + 维护 countif(++hash2[in - 'a'] <= hash1[in - 'a']) count++; if(right - left + 1 > m) // 判断{char out = s[left++];// 出窗⼝ + 维护 countif(hash2[out - 'a']-- <= hash1[out - 'a']) count--; }// 更新结果if(count == m) ret.push_back(left);}return ret;}
};

串联所有单词的子串

题目描述:给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {unordered_map<string,int> originCount;for(auto& e:words){originCount[e]++;}int start=0;vector<int> ans;for(;start<words[0].size();++start){unordered_map<string,int> curCount;if(start+words[0].size()*words.size()>s.size()){break;}int i=start;int j=start;int count=0;while(true){string tmp=s.substr(i,words[0].size());if(tmp.size()!=words[0].size()){break;}if(originCount.end()==originCount.find(tmp)){curCount=unordered_map<string,int>();count=0;j=i+words[0].size();}else{if(curCount[tmp]<originCount[tmp]){++count;++curCount[tmp];}else{while(true){string t=s.substr(j,words[0].size());if(t==tmp){j+=words[0].size();break;}--count;curCount[t]--;j+=words[0].size();}}}if(count==words.size()){ans.push_back(j);}i+=words[0].size();}}return ans;}
};
class Solution
{
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ret;unordered_map<string, int> hash1; // 保存 words ⾥⾯所有单词的频次for(auto& s : words) hash1[s]++;int len = words[0].size(), m = words.size();for(int i = 0; i < len; i++) // 执⾏ len 次{unordered_map<string, int> hash2; // 维护窗⼝内单词的频次for(int left = i, right = i, count = 0; right + len <= s.size(); right += len){// 进窗⼝ + 维护 countstring in = s.substr(right, len);hash2[in]++;if(hash1.count(in) && hash2[in] <= hash1[in]) count++;// 判断if(right - left + 1 > len * m){// 出窗⼝ + 维护 countstring out = s.substr(left, len);if(hash1.count(out) && hash2[out] <= hash1[out]) count--;hash2[out]--;left += len;}// 更新结果if(count == m) ret.push_back(left);}}return ret;}
};

最小覆盖子串

题目描述:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

class Solution {
public:string minWindow(string s, string t) {vector<int> originCount(128,-1);vector<int> curCount(128,0);int i=0;for(;i<t.size();++i){if(-1==originCount[t[i]]){originCount[t[i]]=1;continue;}originCount[t[i]]++;}string ans;int left=0;int right=0;int count=0;for(;left<s.size();++left){if(-1!=originCount[s[left]]){break;}}right=left;for(;right<s.size();++right){if(-1==originCount[s[right]]){continue;}if(curCount[s[right]]<originCount[s[right]]){++count;}curCount[s[right]]++;if(count==t.size()){printf("%d %d\n",left,right);while(true){if(-1==originCount[s[left]]){++left;continue;}else if(curCount[s[left]]>originCount[s[left]]){curCount[s[left]]--;++left;continue;}break;}if(ans.empty()||ans.size()>right-left+1){ans=s.substr(left,right-left+1);}}}return ans;}
};
class Solution {
public:string minWindow(string s, string t) {int hash1[128] = {0}; // 统计字符串 t 中每⼀个字符的频次int kinds = 0;        // 统计有效字符有多少种for (auto ch : t)if (hash1[ch]++ == 0)kinds++;int hash2[128] = {0}; // 统计窗⼝内每个字符的频次int minlen = INT_MAX, begin = -1;for (int left = 0, right = 0, count = 0; right < s.size(); right++) {char in = s[right];if (++hash2[in] == hash1[in])count++;           // 进窗⼝ + 维护 countwhile (count == kinds) // 判断条件{if (right - left + 1 < minlen) // 更新结果{minlen = right - left + 1;begin = left;}char out = s[left++];if (hash2[out]-- == hash1[out])count--; // 出窗⼝ + 维护 count}}if (begin == -1)return "";elsereturn s.substr(begin, minlen);}
};

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

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

相关文章

mysql--二进制安装编译安装yum安装

二进制安装 创建用户和组 [rootlocalhost ~]# groupadd -r -g 306 mysql [rootlocalhost ~]# useradd -r -g 306 -u 306 -d /data/mysql mysql 创建文件夹并添加所属文件用户和组 [rootlocalhost ~]# mkdir -p /data/mysql [rootlocalhost ~]# chown mysql:mysql /data/mysql …

大模型开发和微调工具Llama-Factory-->WebUI

WebUI LLaMA-Factory 支持通过 WebUI 零代码微调大模型。 通过如下指令进入 WebUI llamafactory-cli webui# 如果是国内&#xff0c; # USE_MODELSCOPE_HUB 设为 1&#xff0c;表示模型从 ModelScope 魔搭社区下载。 # 避免从 HuggingFace 下载模型导致网速不畅 USE_MODELSC…

【WPS】【EXCEL】将单元格中字符按照分隔符拆分按行填充到其他单元格

问题&#xff1a;实现如下图的效果 解答&#xff1a; 一、函数 IFERROR(TRIM(MID(SUBSTITUTE($A$2,",",REPT(" ",LEN($A$2))),(ROW(A1)-1)*LEN($A$2)1,LEN($A$2))),"") 二、在单元格C2中填写如下函数 三、全选要填充的单元格并且按CTRLD 函数…

Java有关数组的相关问题

Java中的栈和堆的含义 栈 存储局部变量&#xff1a;栈主要用于存储方法中的局部变量&#xff0c;包括基本数据类型&#xff08;int、double、boolean等&#xff09;和对象的引用&#xff08;不包含对象本身&#xff09;。 遵循后进先出原则&#xff1a;当一个方法被调用时&…

提升阅读体验,Balabolka让文字跃然“声”上

作为一个专业的语音合成工具&#xff0c;Balabolka为用户提供了全方位的文本朗读解决方案。这款软件不仅可以将各类文本实时转换为清晰的语音输出&#xff0c;还能将转换后的音频内容导出为多种主流格式。它强大的兼容性使其能够处理各类电子书和文档格式&#xff0c;让用户可以…

解决`-bash: ./configure:/bin/sh^M:解释器错误: 没有那个文件或目录`的问题

解决`-bash: ./configure:/bin/sh^M:解释器错误: 没有那个文件或目录`的问题 一、错误原因分析二、解决方法方法一:使用`dos2unix`工具方法二:使用`sed`命令方法三:使用`tr`命令方法四:在文本编辑器中转换方法五:在Windows系统中使用适当的工具三、预防措施四、总结在使…

第一部分:基础知识 1. 介绍 --[MySQL轻松入门教程]

什么是MySQL&#xff1f; MySQL 是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它使用结构化查询语言&#xff08;SQL&#xff09;来管理数据。MySQL 由瑞典公司 MySQL AB 开发&#xff0c;现在归 Oracle Corporation 所有。MySQL 是开源软件…

Flink双流Join

在离线 Hive 中&#xff0c;我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢&#xff1f;Flink DataStream API 为我们提供了3个算子来实现双流 join&#xff0c;分别是&#xff1a; join coGroup intervalJoin 下面我们分别详细看一下这…

C# 匿名类型和匿名方法

在C#中&#xff0c;匿名类型和匿名方法是两个非常有用的特性&#xff0c;它们可以帮助我们更方便地处理数据和简化代码的编写。 一、匿名类型 (Anonymous Types) 匿名类型允许你在不显式定义类的情况下创建对象。编译器会自动为你生成一个类&#xff0c;其属性由你在对象初始…

【真正离线安装】Adobe Flash Player 32.0.0.156 插件离线安装包下载(无需联网安装)

网上很多人声称并提供的flash离线安装包是需要联网才能安装成功的&#xff0c;其实就是在线安装包&#xff0c;而这里提供的是真正的离线安装包&#xff0c;无需联网即可安装成功。 点击下面地址下载离线安装包&#xff1a; Adobe Flash Player 32.0.0.156 for IE Adobe Fla…

《Vue 组件化开发:构建可复用的模块》

一、Vue 组件化开发概述 组件化是 Vue.js 的核心概念之一&#xff0c;它允许将界面拆分成独立、可复用的组件&#xff0c;使得开发大型应用变得更加简单和高效。 组件的定义是实现应用中局部功能代码和资源的集合。Vue.js 的组件化用于将 UI 页面分割为若干组件进行组合和嵌套…

Python生日祝福烟花

1. 实现效果 2. 素材加载 2个图片和3个音频 shoot_image pygame.image.load(shoot(已去底).jpg) # 加载拼接的发射图像 flower_image pygame.image.load(flower.jpg) # 加载拼接的烟花图 烟花不好去底 # 调整图像的像素为原图的1/2 因为图像相对于界面来说有些大 shoo…

26页PDF | 数据中台能力框架及评估体系解读(限免下载)

一、前言 这份报告详细解读了数据中台的发展历程、核心概念、能力框架及成熟度评估体系。它从阿里巴巴的“大中台&#xff0c;小前台”战略出发&#xff0c;探讨了数据中台如何通过整合企业内部的数据资源和能力&#xff0c;加速业务迭代、降低成本&#xff0c;并推动业务增长…

C++中输入 不定长数据的方法

在未知 所需要输入数据的长度时 &#xff0c;可以用whilegetchar的方法。 char arr1[60] ;int i 0;char c ;while ((c getchar())! \n && c! EOF){arr1[i] c;i;}arr1[i]\0; 这里正常输入字符都是没问题的&#xff0c;while里面的内容都可以正常执行&#xff0c; 当…

Linux系统硬件老化测试脚本:自动化负载与监控

简介&#xff1a; 这篇文章介绍了一款用于Linux系统的自动化硬件老化测试脚本。该脚本能够通过对CPU、内存、硬盘和GPU进行高强度负载测试&#xff0c;持续运行设定的时长&#xff08;如1小时&#xff09;&#xff0c;以模拟长时间高负荷运行的环境&#xff0c;从而验证硬件的稳…

如何分段存储Redis键值对

说明&#xff1a;本文介绍针对一个value过长的键值对&#xff0c;如何分段存储&#xff1b; 场景 当我们需要存入一个String类型的键值对到Redis中&#xff0c;如下&#xff1a; &#xff08;缓存接口&#xff09; public interface CacheService {/*** 添加一个字符串键值…

C-操作符

操作符种类 在C语言中&#xff0c;操作符有以下几种&#xff1a; 算术操作符 移位操作符 位操作符 逻辑操作符 条件操作符 逗号表达式 下标引用&#xff0c;函数调用 拓展&#xff1a;整型提升 我们介绍常用的几个 算术操作符 &#xff08;加&#xff09;&#xff…

RabbitMQ 客户端 连接、发送、接收处理消息

RabbitMQ 客户端 连接、发送、接收处理消息 一. RabbitMQ 的机制跟 Tcp、Udp、Http 这种还不太一样 RabbitMQ 服务&#xff0c;不是像其他服务器一样&#xff0c;负责逻辑处理&#xff0c;然后转发给客户端 而是所有客户端想要向 RabbitMQ服务发送消息&#xff0c; 第一步&a…

浅析大数据时代下的网络安全

一、大数据时代下网络安全的现状 在全球化进程不断深入发展的情况下&#xff0c;互联网行业发展速度也更加迅猛&#xff0c;人们对网络信息的需求量不断增加&#xff0c;所以目前已经进入了大数据时代。 随着计算机技术的不断发展&#xff0c;我国互联网网络规模、网民数量、…

【SQL常用日期函数(二)】

SQL 常用日期函数-基于 Impala 3.4.0 接之前 SQL常用日期函数&#xff08;一&#xff09;介绍了实现计算上年末、上级末、上月末、上年同期的方法和函数&#xff0c;这次继续分享常用的SQL日期函数及使用场景。包括&#xff1a;DAYOFWEEK 函数、TRUNC 函数、LAST_DAY 函数。 …