滑动窗口篇——如行云流水般的高效解法与智能之道(1)

前言:

上篇我们介绍了双指针算法,并结合具体题目进行了详细的运用讲解。本篇我们将会了解滑动窗口。滑动窗口是一种常用的算法技巧,主要用于处理子数组、子串等具有“窗口”特性的题目。柳暗花明,乃巧解复杂问题的高效之道。

一. 长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

题目分析:

1. 题目要求寻找一个子数组,数组内所有元素相加之和大于等于target,且要求该子数组的长度最小

2. 如果找到则返回最小子数组的长度,如果没有找到则返回0

注意:题目中所给的数组内所有元素均为正整数,且target也为正整数!!! 

思路讲解:

暴力解法(会超时):

「从前往后」枚举数组中的任意⼀个元素,把它当成起始位置。然后从这个「起始位置」开始,然
后寻找⼀段最短的区间,使得这段区间的和「⼤于等于」⽬标值。
将所有元素作为起始位置所得的结果中,找到「最⼩值」即可。

滑动窗口:

暴力解法超时的原因为进行了大量冗余的遍历。

我们需要明白,由于所有的元素均为正整数,当子数组的区间长度在原有基础下增大时,和必然增大,反之,则必然减小,即子数组区间和的大小与区间长度存在单调性。

假设 target = 7, nums = [2, 3, 1, 2, 4, 3]:

初始状态:left = 0, right = 0, sum = 2,窗口未达到 target。
入窗口:将 right 向右移动,直到窗口和 sum = 9,满足条件。
出窗口:移动 left,将子数组 [4, 3] 缩小到长度 2。

因此,其解法可总结为入窗口,出窗口,更新情况三大步骤。

如图:

代码实现:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum=0;//子数组的和
        int n=nums.size(),ret=INT_MAX;//由于是求最小值,因此可首先假定其为int的最大值
        for(int left=0,right=0;right<n;right++)
        {
            sum+=nums[right];//进窗口
            while(sum>=target)
            {
                ret=min(ret,right-left+1);
                sum-=nums[left++];
            }//出窗口,更新ret,为下一轮遍历做准备
        }
        return ret==INT_MAX?0:ret;
        
    }
};

优势分析:

1. 时间复杂度为O(n),远远优于暴力解法

2. 在处理重复遍历问题时,我们直接采取改变窗口区间长度的方式,利用先前分析过的单调性,以left和right对其进行控制,使效率大大提高。

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

题目链接:3. 无重复字符的最长子串 - 力扣(LeetCode)

题目分析:

1. 题目要求找出一个无重复长度的子串,且该子串要求长度最长。

2. 子串的含义同子数组类似,一定要求连续,最大可为字符串本身。

思路讲解: 

暴力解法(不会超时,可以通过):

枚举「从每⼀个位置」开始往后,⽆重复字符的⼦串可以到达什么位置。找出其中⻓度最⼤的。
可在往后寻找⽆重复⼦串能到达的位置时,利⽤「哈希表」统计出字符出现的频次,来判断什么时候⼦串出现了重复元素。

代码实现:

class Solution {
public:
 int lengthOfLongestSubstring(string s) {
 int ret = 0; // 记录结果
 int n = s.length();
 // 1. 枚举从不同位置开始的最⻓重复⼦串
 // 枚举起始位置
 for (int i = 0; i < n; i++)
 {

 // 创建⼀个哈希表,统计频次
 int hash[128] = { 0 };
 
 // 寻找结束为⽌
 for (int j = i; j < n; j++)
 {
 hash[s[j]]++; // 统计字符出现的频次
 if (hash[s[j]] > 1) // 如果出现重复的
 break;
 
 // 如果没有重复,就更新 ret
 ret = max(ret, j - i + 1);
 }
 }
 // 2. 返回结果
 return ret;
 }
};

 滑动窗口:

研究的对象子串仍旧是一段连续的区间,因此可以考虑使用滑动窗口来解决。

1. 我们可以使用哈希来进行字符的映射,由于窗口内所有元素都是不重复的,因此我们可以让右端元素进入窗口,并记录其字符出现频次。

2. 当字符出现频次不全为0时,即代表出现了重复元素,需要让左侧元素逐次出窗口,直至恢复频次全为0为止。

3. 当完全遍历后,此时窗口长度即为最长字串的长度。

代码实现:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128]={0};//模拟哈希表
        int n=s.size();
        int ret=0;
        for(int left=0,right=0;right<n;right++)
        {
            hash[s[right]]++;//入窗口
            while(hash[s[right]]>1)
            {
                hash[s[left++]]--;//出窗口
            }
            ret=max(ret,right-left+1);//更新子串长度
        }
        return ret;
        
    }
};

 三. 最大连续1的个数lll

题目链接:1004. 最大连续1的个数 III - 力扣(LeetCode)

题目分析:

1. 给定一个元素为1或0的数组,以及一个正整数K,可以在K的范围内把0变为1,求最长连续区间内均为1的长度。

2. 问题可转化为,求一段最长的连续区间,区间内0的个数在K范围内。

思路讲解:

滑动窗口:

此题仍为求一段连续区间的长度,因此也可以用滑动窗口来解决。

 1. 利用zere记录区间内0的个数,当zero小于K时,即可令右端元素进窗口

 2. 当zero>K时,需要令左端元素出窗口,如果左端元素为0,则令zero-1,直至zero<K为止。

3. 当完全遍历后,窗口长度即为最大连续区间的长度。 

代码实现:

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int zero=0;//记录0的个数
        int n=nums.size(),ret=0;
        for(int left=0,right=0;right<n;right++)
        {
            if(nums[right]==0)
            {
                zero++;
            }//记录0的增长情况
            while(zero>k)
            {
                if(nums[left++]==0)
                {
                    zero--;
                }
            }//出窗口
            ret=max(ret,right-left+1);//更新窗口长度
        }
        return ret;
        
    }
};

小结:本篇介绍了滑动窗口的含义并结合基础题型加以讲解练习,下篇讲为大家分享滑动窗口的进阶题目,欢迎各位佬前来支持斧正!!! 

 

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

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

相关文章

数据结构-树状数组专题(2)

一、前言 接上回树状数组专题&#xff08;1&#xff09;&#xff0c;这次主要介绍差分跟树状数组联动实现区间更新 二、我的模板 重新放了一遍&#xff0c;还是提一嘴&#xff0c;注意下标从0开始&#xff0c;区间左闭右开 template <typename T> struct Fenwick {in…

QA|使用 MapleSim 模拟卷料生产 (Converting)和卷对卷系统 (R2R)

使用 MapleSim 模拟卷料生产 (Converting)和卷对卷系统 (R2R) 纸张、薄膜、塑料、金属箔、新能源电池和卷料生产设备 (converting equipment) 的制造商正在转向建模和仿真&#xff0c;以提升卷料处理的设备性能和产品质量。MapleSim 卷料处理库提供了专业的建模元件以及功能&a…

2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程

此套源码功能强大&#xff0c;支持APK脱壳、注入、网络验证、注册机、引流弹窗、更新弹窗和公告等功能&#xff0c;并具有强大的系统应用管理端&#xff0c;可轻松管理用户数量和卡密状态等数据统计。armpro脱壳软件可在线修改手机文件和游戏数据&#xff0c;并可添加会员功能、…

汉诺塔(hanio)--C语言函数递归

文章目录 前言一、汉诺塔的图解二、问题分析总结 前言 什么是汉诺塔&#xff1f; 汉诺塔(Tower of Hanoi)&#xff08;也称河内塔&#xff09;是有法国数学家爱德华卢卡斯于1883年发明的一道智力题。它源于印度的一个古老传说&#xff1a;大梵天创造世界的时候做了三根钻石柱子…

【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析

前言&#xff1a;本节内容讲述mysql里面的函数的概念&#xff0c; 在mysql当中&#xff0c; 内置了很多函数工作。 这些函数丰富了我们的操作。 比如字符串函数、数据函数以及一些其他函数等等。 ps:友友们学习了表的基本操作后就可以观看本节内容啦! 目录 日期函数 current_…

Is:cannat access /data: Input/output error

说明&#xff1a; 1&#xff09;访问应用业务&#xff0c;输入账号密码报如下图所示&#xff1a;invalid login. 2&#xff09;登录服务器查看数据日志&#xff0c;报如下图所示&#xff1a;ls:cannot access /data: Input/output error 3&#xff09;查看日志dmesg |grep erro…

Python MySQL SQLServer操作

Python MySQL SQLServer操作 Python 可以通过 pymysql 连接 MySQL&#xff0c;通过 pymssql 连接 SQL Server。以下是基础操作和代码实战示例&#xff1a; 一、操作 MySQL&#xff1a;使用 pymysql python 操作数据库流程 1. 安装库 pip install pymysql2. 连接 MySQL 示例 …

迅为RK3562开发板直连电脑配置方法(无线上网)

概述 由于环境限制&#xff0c;笔记本电脑和开发板无法通过路由器连接起来&#xff0c;所以本文的目的是要实现笔记本电脑和虚拟机能够通过 WIFI 上网&#xff0c;并且开发板通过网线连接笔记本电脑和虚拟机在同一个网段内&#xff0c;最终实现 TFTP 或 NFS 来进行开发调试。 通…

Mono Repository方案与ReactPress的PNPM实践

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 Mono Repository方案与ReactPress的PNPM实践 在当今软件开发领域&#xff0c;Mono Repository&#xff08;简称Monorepo&#xff09;已成为一种流行的代码管理方式&#xff0c;特…

timedatectl命令修改时间和时区

1.默认情况下&#xff0c;Linux系统通常每64分钟进行一次NTP时间同步。但是&#xff0c;这可以通过编辑/etc/ntp.conf文件来修改。在/etc/ntp.conf中设置minpoll和maxpoll参数。 timedatectl可以用来查询和更改系统时间设定&#xff0c;同时可以设定和修改时区信息。 一、查…

基于Opencv的图像处理软件

目录 一、背景及意义介绍背景意义 二、概述一、背景及意义介绍背景意义 三、论文思路解决问题 四、复现过程&#xff08;一&#xff09;图像处理模块二&#xff09;图形界面模块&#xff08;一&#xff09;图像处理模块实现步骤&#xff08;二&#xff09;图形界面模块实现步骤…

HTML的自动定义倒计时,这个配色存一下

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>自定义倒计时</title><style>* {mar…

私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?

在当今数字化、网络化的时代背景下&#xff0c;视频监控技术已广泛应用于各行各业&#xff0c;成为保障安全、提升效率的重要工具。然而&#xff0c;面对复杂多变的监控需求和跨区域、网络化的管理挑战&#xff0c;传统的视频监控解决方案往往显得力不从心。 EasyCVR视频融合云…

MacOS通过X11转发远程运行virt-manager进行虚机分配

今天需要通过本地macbook机器连接远程物理机&#xff0c;执行虚机分配&#xff0c;现有文档仅提供window环境安装&#xff0c;如下整理Mac环境下的安装步骤 操作篇 前提条件 支持x11转发的terminal&#xff0c;我本地使用iTerm2&#xff1b;本地安装XQuartz&#xff0c;作为…

【每天学点AI】实战图像增强技术在人工智能图像处理中的应用

图像增强&#xff08;Image Enhancement&#xff09;是人工智能和计算机视觉中一项重要的技术&#xff0c;也是人工智能数据集预处理的一个重要步骤。它旨在提高图像的质量&#xff0c;使其在视觉上更加清晰、细节更丰富。这项技术在自动驾驶、医疗诊断、安防监控等领域有着广泛…

hbase mongodb hive starrocks比较

本文是在学习大数据的几个数据存储系统相关的组件所记录下来的&#xff0c;主要是不同组件的基础概念初步了解与对比。 NoSql 在大数据时代&#xff0c;虽然RDBMS很优秀&#xff0c;但是面对快速增长的数据规模和日渐复杂的数据模型&#xff0c;RDBMS渐渐力不从心&#xff0c…

STM32端口模拟编码器输入

文章目录 前言一、正交编码器是什么&#xff1f;二、使用步骤2.1开启时钟2.2配置编码器引脚 TIM3 CH1(PA6) CH2 (PA7)上拉输入2.3.初始化编码器时基2.4 初始化编码器输入2.5 配置编码器接口2.6 开启定时器2.7获取编码器数据 三、参考程序四、测试结果4.1测试方法4.2串口输出结果…

wireshark使用lua解析自定义协议

wireshark解析自定义协议 1.自定义的lua放入路径2.修改init.lua2.1 开启lua2.2 init.lua文件最后加入自己的lua文件位置&#xff0c;这里需要确保与自己的文件名相同 3.编写lua4.编写c抓包5.wireshark添加自定义协议如何加调试信息 1.自定义的lua放入路径 一般是自己软件的安装…

基于docker进行任意项目灵活发布

引言 不管是java还是python程序等&#xff0c;使用docker发布的优势有以下几点&#xff1a; 易于维护。直接docker命令进行管理&#xff0c;如docker stop、docker start等&#xff0c;快速方便无需各种进程查询关闭。环境隔离。项目代码任何依赖或设置都可以基本独立&#x…

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…