C++算法——滑动窗口

一、长度最小的子数组

1.链接

209. 长度最小的子数组 - 力扣(LeetCode)

2.描述

3.思路

本题从暴力求解的方式去切入,逐步优化成“滑动窗口”,首先,暴力枚举出各种组合的话,我们先让一个指针指向第一个,然后往后逐一遍历区间,也就是穷举出所有的子数组,但根据题目要求,当我们穷举出大于或者等于target的区间时,右边指针再向后遍历穷举的结果将没有意义,所以不需要再去往后走,而是进行下一轮遍历(前提是本题中数据全是正整数),当左指针往后走一步后,穷举的思路需要我们从头再走一次重复的数据,此时我们对其进行优化,定义一个sum值去记录区间数据,就可以不需要再次遍历一次,经过优化后,我们会发现,解题思路就变成了:

定义两个左右指针,一起从头往前走,并且记录两个指针区间的和sum,right指针往后,当大于等于目标值时,则停下记录长度,然后left走一步,进行判断是否仍然满足大于等于目标值,若是满足则让left继续走,当长度出现比原先短的区间时,进行更新最小区间的长度,left走到小于目标值时,让right进行往前走,直到right遍历完一遍数组,这种两个指针同向一起走的思路叫做“滑动窗口”

4.参考代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int left = 0;
        int right = 0;
        int sum = nums[0];
        int len = 0;
        while(right < nums.size())
        {
            if(sum < target)
            {
                ++right;
                if(right < nums.size())
                    sum+=nums[right];
            }
            else
            {
                len = len == 0 ? right-left+1 :  min(len,right - left + 1);
                if(len == 1) break;
                sum-=nums[left++];
            }
        }
        return len;
    }
};

二、无重复字符的最长子串

1.链接

3. 无重复字符的最长子串 - 力扣(LeetCode)

2.描述

3.思路

由于是对子串进行判断,子串是一段连续的区间,所以我们可以尝试采用滑动窗口的思路解决

满足窗口滑动的条件就是:判断窗口内是否有重复字符,可以利用哈希表去进行统计

当没有重复时则right往前走,当有重复时则left往前,这个过程中记录下最长的子串

4.参考代码

class Solution 
{
public:
    int lengthOfLongestSubstring(string s) 
    {
        if(s.size() == 0)
        {
            return 0;
        }
        int left = 0;
        int right = 0;
        int len = 0;
        set<char> hash;
        while(right < s.size())
        {
            if((hash.insert(s[right])).second)//插入成功意味着没有重复
            {
                right++;
                len = max(len,right-left);
            }
            else//出现重复
            {
                hash.erase(s[left++]);
            }
        }
        return len;
    }
};

三、最大连续1的个数|||

1.链接

1004. 最大连续1的个数 III - 力扣(LeetCode)

2.描述

3.思路

可以将题意转化为,在一段区间内,0的数量不能超过k个,利用滑动窗口去解决

当超过k个时,left往前走,直到将最前面的0给退出窗口,没有超过时,则right往前走,不断扩大窗口,过程中记录下窗口长度最大的值

4.参考代码

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) 
    {
        int left = 0;
        int right= 0;
        int n = nums.size();
        int len = 0;
        while(right < n)
        {
            while(right < n && (k != 0 || nums[right] == 1))
            {
                if(nums[right] == 0)
                {
                    k--;
                }
                right++;
                len = max(len,right-left);
            }
            while(left < n && k == 0)
            {
                if(nums[left++] == 0)
                    k++;
            }
        }
        return len;
    }
};

四、将x减到0的最小操作数

1.链接

1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

2.描述

3.思路

我们可以先将问题转换成,在数组内找到一段最长连续的子区间之和会刚好等于数组之和减去x的值

将问题变成在数组中找一段最长的连续子区间之和等于目标值的问题后,我们就可以使用滑动窗口的思路去解决,思路可以参考第一题“长度最小的子数组”

4.参考代码

class Solution 
{
public:
    int minOperations(vector<int>& nums, int x) 
    {
        int n = nums.size();
        int sum = 0;
        for(auto n:nums)
        {
            sum+=n;
        }
        int target = sum - x;
        if(target < 0) return -1;
        //找到最长的子区间
        int len = -1;
        for(int left = 0,right = 0,s = 0; right < n;right++ )
        {
            s += nums[right];//进窗口
            while(s > target)//出窗口
            {
                s-=nums[left++];
            }
            if(s == target)
            {
                len = max(len,right-left+1);
            }
        }
    
        return len == -1 ? len : n-len;
    }
};

五、水果成篮

1.链接

904. 水果成篮 - 力扣(LeetCode)

2.描述

3.思路

根据题意,利用滑动窗口的思路,当窗口内的水果种类超过两种时则开始出窗口,过程中记录下窗口的长度,利用哈希表去进行统计

4.参考代码

class Solution {
public:
    int totalFruit(vector<int>& fruits) 
    {
        map<int,int> hash;
        int ret = 0;
        for(int left = 0,right = 0;right<fruits.size();right++)
        {
            hash[fruits[right]]++;
            while(hash.size()>2)
            {
                hash[fruits[left]]--;
                if(hash[fruits[left]] == 0)
                {
                    hash.erase(fruits[left]);
                }
                left++;
            }
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};

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

1.链接

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

2.描述

3.思路

4.参考代码

class Solution 
{
public:
    vector<int> findAnagrams(string s, string p) 
    {
        int hash1[26] = {0};
        int hash2[26] = {0};
        for(auto c:p)
        {
            hash1[c-'a']++;
        }
        int m = p.size();
        vector<int> ret;
        for(int left = 0,right = 0,count = 0; right < s.size(); right++)
        {
            char in = s[right];
            hash2[in - 'a']++;//入窗口
            if(hash2[in - 'a'] <= hash1[in - 'a']) count++;//维护count
            char out = s[left];
            if(right-left+1 > m)//出窗口
            {
                if(hash2[out - 'a'] <= hash1[out - 'a']) count--;//维护count
                hash2[out - 'a']--;
                left++;
            }
            //判断目标
            if(count == m)
            {
                ret.push_back(left);
            }
        }
        return ret;
    }
};

七、串联所有单词的子串

1.链接

30. 串联所有单词的子串 - 力扣(LeetCode)

2.描述

3.思路

4.参考代码

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        int len = words[0].size();
        unordered_map<string,int> m1;
        unordered_map<string,int> m2;
        vector<int> ret;
        for(auto& s:words) m1[s]++;
        for(int i = 0;i<len;i++)//以i位置为起点
        {
            for(int left = i,right = i+len-1,count = 0; right < s.size() ; right+=len)//滑动窗口
            {
                string in = s.substr(right-len+1,len);
                m2[in]++;//入窗口
                if(m2[in] <= m1[in]) count++;//维护count
                if(right-left+1 > len*words.size())//出窗口
                {
                    string out = s.substr(left,len);
                    if(m2[out] <= m1[out]) count--;
                    m2[out]--;
                    left+=len;
                }
                if(count == words.size()) ret.push_back(left);
            }
            m2.clear();
        }
        return ret;
    }
};

八、最小覆盖子串

1.链接

76. 最小覆盖子串 - 力扣(LeetCode)

2.描述

3.思路

有了前面的经验,不难想到这题该怎么用滑动窗口解决,根据题意分析,我们知道首先将t内的字符记录到哈希表hash1中,然后让滑动窗口的右侧不断的往前走,直到满足题目条件,即滑动窗口内的字符串包含了t内的字符,此时让left往前收缩,记录下最小的区间,然后直到不再满足条件后,让right继续往后找满足条件的子串,最终记录下最短的那个子串即可,当然,还有如何优化哈希比较的细节需要注意,以及对于如何记录下最短子串的考量

4.参考代码

class Solution {
public:
    string minWindow(string s, string t) 
    {
        int n = s.size();
        int hash1[128] = {0};
        int hash2[128] = {0};
        for(auto& c : t)  hash1[c]++;
        int begin = -1; int len = s.size()+1;
        for(int left = 0,right = 0,count = 0;right < n;right++)
        {
            char in = s[right];
            hash2[in]++;
            if(hash2[in] <= hash1[in]) count++;
            while(count == t.size())
            {
                if(right-left+1 < len)
                {
                    len = right-left+1;
                    begin = left;
                }
                char out = s[left++];
                if(hash2[out] <= hash1[out]) count--;
                hash2[out]--;
            }
        }
        if(begin == -1) return "";
        else return s.substr(begin,len);
    }
};

总结

本章节主要整理了关于滑动窗口的算法思想,由简单到困难逐步递进,整理了八道相关例题以及思路解析提供参考,也可以通过链接去做

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Qt学习笔记 01】Qt 背景介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt 背景介绍 文章编号&#xff1a;Qt 学习笔记 / 01 文章目录 Qt 背景…

AttributeError: ‘Namespace‘ object has no attribute ‘EarlyStopping‘

报错原因 这个报错信息表明在Python脚本train.py中尝试访问命令行参数args.EarlyStopping时出错&#xff0c;具体错误是AttributeError: Namespace对象没有名为EarlyStopping的属性。 在Python的argparse模块中&#xff0c;当我们通过命令行传递参数并解析时&#xff0c;解析…

UGUI 进阶

UI事件监听接口 目前所有的控件都只提供了常用的事件监听列表 如果想做一些类似长按&#xff0c;双击&#xff0c;拖拽等功能是无法制作的 或者想让Image和Text&#xff0c;RawImage三大基础控件能够响应玩家输入也是无法制作的 而事件接口就是用来处理类似问题 让所有控件都…

10秒钟用python接入讯飞星火API(保姆级)

正文&#xff1a; 科大讯飞是中国领先的人工智能公众公司&#xff0c;其讯飞星火API为开发者提供了丰富的接口和服务&#xff0c;以支持各种语音和语言技术的应用。 步骤一&#xff1a;注册账号并创建应用 首先&#xff0c;您需要访问科大讯飞开放平台官网&#xff0c;注册一个…

dcoker 下redis设置密码

修改Docker里面Redis密码 Redis是一个开源的内存数据结构存储系统&#xff0c;常用于缓存、消息队列和数据持久化等场景。在使用Docker部署Redis时&#xff0c;默认情况下是没有设置密码的&#xff0c;这可能会导致安全隐患。因此&#xff0c;为了保证数据的安全性&…

2024环境,资源与绿色能源国际会议(ICERGE2024)

2024环境&#xff0c;资源与绿色能源国际会议(ICERGE2024) 会议简介 2024环境、资源与绿色能源国际会议(ICERGE2024)将于2024年在三亚举行。该会议是一个围绕环境、资源与绿色能源研究领域的国际学术交流活动。 会议主题包括但不限于环境科学、环境工程、资源利用、绿色能源开…

微信小程序上传代码到远程仓库

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

MySQL安装卸载

目录 1.概述 2.安装 2.1.安装 2.2.配置 3.卸载 3.1.停服务 3.2.卸载组件 3.3.删除安装目录 3.4.删除数据目录 3.5.检查残留 1.概述 MySQL是一个广受欢迎的关系型数据库管理系统&#xff0c;最初由瑞典的MySQL AB公司开发&#xff0c;现在是Oracle旗下的产品。作为最流…

海外媒体宣发技巧解析从而提升宣发效果

在当今全球化的媒体环境下&#xff0c;海外媒体宣发是企业和品牌推广的重要手段。然而&#xff0c;要在海外市场取得成功&#xff0c;一味地复制国内的宣发策略是行不通的。要想提升宣发效果&#xff0c;就必须了解并掌握一些海外媒体宣发的技巧。世媒讯一家从事海内外媒体的推…

1111111

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

【中文视觉语言模型+本地部署 】23.08 阿里Qwen-VL:能对图片理解、定位物体、读取文字的视觉语言模型 (推理最低12G显存+)

项目主页&#xff1a;https://github.com/QwenLM/Qwen-VL 通义前问网页在线使用——&#xff08;文本问答&#xff0c;图片理解&#xff0c;文档解析&#xff09;&#xff1a;https://tongyi.aliyun.com/qianwen/ 论文v3. : 一个全能的视觉语言模型 23.10 Qwen-VL: A Versatile…

简直了,被“Java并发锁”问题追问到自闭...

分享是最有效的学习方式。 博客&#xff1a;https://blog.ktdaddy.com/ 故事 地铁上&#xff0c;小帅双目空洞地望着窗外…绝望&#xff0c;发自内心地感到绝望… 距离失业已经过去两个月了&#xff0c;这是小帅接到的第四次面试邀请。“回去等通知吧…”,简简单单的六个字&a…

汽车贴膜改色小程序源码 汽车配色小程序源码 车身改色app源码 带后台 带数据

汽车贴膜改色小程序源码 车身改色app源码 汽车配色小程序源码 带后台 带数据 整站源码&#xff0c;包含完整前端小程序&#xff0c;后台源码&#xff0c;数据库数据。 直接部署&#xff0c;就能使用&#xff0c;源码素材远程开发&#xff0c;可以定制开发。 全开源&#xff0c;…

关于ITIL认证您需要了解的一切

这是一篇关于从业人员、领导者和 ITSM 爱好者指南。ITIL4于2019 年发布。最新版本的 IT 服务管理&#xff08;ITSM&#xff09;最佳实践从传统的生命周期方法转变为服务价值体系模型&#xff0c;重点关注价值共创、向业务交付成果以及与其他最佳实践框架的融合。 新版本的框架…

商城网站-礼品网站首页html+css+js+说明文档

网页设计与网站建设作业htmlcssjs 预览 说明 单页面&#xff0c;轮播图 获取&#xff1a;https://hpc.baicaitang.cn/2077.html

西门子SMART200PLC与罗克韦尔(AB)PLC之间以太网通讯

智能网关NET422WX支持多点对多点的PLC之间通讯&#xff0c;支持以太网&#xff0c;串口设备混合数据交换&#xff1b;无需编程开发&#xff0c;只须配置数据的起始地址和数量即可&#xff0c;支持热插拔&#xff0c;断电重启后自恢复运行&#xff0c;支持网络跨网段&#xff0c…

Redis断连从框架层面该如何抢救?

前言 上周发生了一件鸡飞狗跳的线上事故&#xff0c;六节点的Redis-Cluster集群所在的大部分机器因为网络带宽问题断连了&#xff0c;排查之后发现是那几台物理机带宽被占满了&#xff0c;导致整个集群因为槽位不满16384而请求失败。并且因为没有考虑缓存失效问题&#xff0c;…

AI改写文案的注意事项

AI改写文案的注意事项 随着人工智能技术的不断发展&#xff0c;AI改写文案成为了一种新兴的应用场景。通过AI改写文案&#xff0c;可以快速生成大量内容&#xff0c;节省时间和人力成本&#xff0c;但在实际应用中也需要注意一些问题和注意事项。 1. 确保内容原创性 尽管AI改…

NumPy创建ndarray数组大揭秘

1.使用 np.array() 创建 使用 np.array() 由 python list 创建 n np.array(list) 注意 numpy 默认 ndarray 的所有元素的类型是相同的 如果传进来的列表中包含不同的类型&#xff0c;则统一为同一类型&#xff0c;优先级&#xff1a;str > float > int ndarray 的常…

HarmonyOS 应用开发之同步任务开发指导 (TaskPool和Worker)

同步任务是指在多个线程之间协调执行的任务&#xff0c;其目的是确保多个任务按照一定的顺序和规则执行&#xff0c;例如使用锁来防止数据竞争。 同步任务的实现需要考虑多个线程之间的协作和同步&#xff0c;以确保数据的正确性和程序的正确执行。 由于TaskPool偏向于单个独…