滑动窗口详解

目录

一、滑动窗口的特定步骤:

二、题目解析

1、⻓度最⼩的⼦数组---点击跳转题目

3、最⼤连续 1 的个数 III----点击跳转题目

4、将 x 减到 0 的最⼩操作数----点击跳转题目

5、⽔果成篮----点击跳转题目


滑动窗口是双指针算法中细分的一种,它由暴力枚举算法优化而来,解决的是同向双指针问题;当一个题目在暴力解法中发现枚举时其实可以不用把“指针”往回走,就可以使用滑动窗口的思想来解决。也就是滑动窗口通过题目的某种性质,忽略了很多无效枚举,维护两个指针间的区间保持某种性质,从而把时间复杂度从O(n^2)优化到O(n)

只要题目的研究对象是一段连续区间或者能转化为一段连续区间,就可以考虑用滑动窗口来做,思路不清晰时可以先想题目的暴力枚举,从中优化而来

一、滑动窗口的特定步骤:

  • 定义指针left、right
  • 确定如何进窗口
  • 判断(指针内区的某种性质进入循环)用while循环做判断
  • 通过判断不断出窗口,使得指针内的区间满足性质
  • 确定在哪一步更新结果

滑动窗口的代码形式是双重循环,外层是right指针遍历,内层是为了指针内区间满足某种性质而不断出窗口;虽然是双重循环,但是时间复杂度只有O(n)

二、题目解析

1、⻓度最⼩的⼦数组---点击跳转题目

由于此问题分析的对象是「⼀段连续的区间」,因此可以考虑「滑动窗⼝」的思想来解决这道题。 让滑动窗⼝满⾜:从 i 位置开始,窗⼝内所有元素的和⼩于 target (那么当窗⼝内元素之和 第⼀次⼤于等于⽬标值的时候,就是 i 位置开始,满⾜条件的最⼩⻓度)。 做法:将右端元素划⼊窗⼝中,统计出此时窗⼝内元素的和:

▪ 如果窗⼝内元素之和⼤于等于 target :更新结果,并且将左端元素划出去的同时继续判 断是否满⾜条件并更新结果(因为左端元素可能很⼩,划出去之后依旧满⾜条件)

▪ 如果窗⼝内元素之和不满⾜条件: right++ ,让下⼀个元素进⼊窗⼝。

代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int l = 0, r = 0;
        long long sum = 0;
        int len = INT_MAX;

        while(r < nums.size())
        {
            sum += nums[r];//进窗口
            while(sum >= target)//判断
            {
                len = min(r - l + 1,len);//更新结果
                sum -= nums[l++];//出窗口
            }
            r++;
        }
       
       return len == INT_MAX ? 0 : len;
    }
};

时间复杂度:虽然代码是两层循环,但是我们的 left 指针和 right 指针都是不回退的,两者 最多都往后移动 n 次。因此时间复杂度是 O(n)

2、⽆重复字符的最⻓⼦串----点击跳转题目

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

优化:研究的对象依旧是⼀段连续的区间,因此继续使⽤「滑动窗⼝」思想来优化。
让滑动窗⼝满⾜:窗⼝内所有元素都是不重复的。
做法:右端元素 ch 进⼊窗⼝的时候,哈希表统计这个字符的频次:
▪ 如果这个字符出现的频次超过 1 ,说明窗⼝内有重复元素,那么就从左侧开始划出窗⼝,
直到 ch 这个元素的频次变为 1 ,然后再更新结果。
▪ 如果没有超过 1 ,说明当前窗⼝没有重复元素,可以直接更新结果

代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) 
    {
        int hash[128];//下标表示字符,数组存储字符个数,可以快速查找每个字符个数
        int l = 0, r = 0;
        int len = 0;

        while(r < s.size())
        {
            hash[s[r]]++;//进窗口
            while(hash[s[r]] > 1)//判断
                hash[s[l++]]--;//出窗口
            len = max(len,r - l + 1);//更新结果
            r++;
        }
        return len;
    }
};

3、最⼤连续 1 的个数 III----点击跳转题目

不要去想怎么翻转,不要把问题想的很复杂,这道题的结果⽆⾮就是⼀段连续的 1 中间塞了 k 个 0 嘛。 因此,我们可以把问题转化成:求数组中⼀段最⻓的连续区间,要求这段区间内 0 的个数不超 过 k 个。 比特就业课 既然是连续区间,可以考虑使⽤「滑动窗⼝」来解决问题。

滑动窗口的性质:区间内至多有k个0,维护这个性质即可

代码:

class Solution {
public:
    //转化:找到最长的子数组,0的个数不超过k个
    int longestOnes(vector<int>& nums, int k) 
    {
        int l = 0, r = 0, len = 0;
        int zero = 0;

        while(r < nums.size())
        {
            if(nums[r] == 0) zero++;//进窗口
            while(zero > k)//判断性质是否满足
            {
                if(nums[l++] == 0) zero--;//出窗口
            }
            len = max(len,r - l + 1);//性质满足时更新结果
            r++;
        }
        return len;
    }
};

4、将 x 减到 0 的最⼩操作数----点击跳转题目

题⽬要求的是数组「左端+右端」两段连续的和为 x 的最短数组,正难则反,我们可以转化成求数组内⼀段连续的、和为 sum(nums) - x 的最⻓数组。此时,就是熟悉的「滑动窗⼝」问题了

target = sum - x

滑动窗口的性质:区间内和为target

题目所求的最小操作数也就是 nums的个数减去最长子数组

代码:

class Solution {
public:
    //转化:找到最长子数组,和为 sum - x
    int minOperations(vector<int>& nums, int x) 
    {
        int sum=0, target, len = -1;
        // sum = accumulate(nums.begin(), nums.end(), 0);
        for(auto e : nums) sum += e;
        target = sum - x;
        if(target < 0) return -1; //sum < x的情况不可能把x减为0
        int l = 0, r = 0;
        
        long long s = 0;//区间内的和
        while(r < nums.size())
        {
            s += nums[r];//进窗口
            while(s > target)//需要的是s等于target
            {
                s -= nums[l++];//出窗口
            }
            if(s == target) //上面循环跳出来时s可能等于或小于target
                len = max(len,r - l + 1);//更新结果
            r++;
        }
        if(len == -1) return len;
        else return nums.size() - len;
    }
};

5、⽔果成篮----点击跳转题目

研究的对象是⼀段连续的区间,可以使⽤「滑动窗⼝」思想来解决问题。 让滑动窗⼝满⾜:窗⼝内⽔果的种类只有两种。

做法:右端⽔果进⼊窗⼝的时候,⽤哈希表统计这个⽔果的频次。这个⽔果进来后,判断哈希表的⼤⼩:

▪ 如果⼤⼩超过 2:说明窗⼝内⽔果种类超过了两种。那么就从左侧开始依次将⽔果划出窗 ⼝,直到哈希表的⼤⼩⼩于等于 2,然后更新结果;

▪ 如果没有超过 2,说明当前窗⼝内⽔果的种类不超过两种,直接更新结果 len。

代码:

class Solution {
public:
    //找出一个最长子数组,数组中最多两种水果
    int totalFruit(vector<int>& fruits) 
    {
        const int N = 1e5 + 10;
        //下标表示水果种类,数组元素表示区间中这种水果放了几次
        int hash[N] = {0};
        int l = 0, r = 0;
        int kinds = 0,len = 0;//kinds表示区间内水果种类数
        while(r < fruits.size())
        {
           if( hash[fruits[r]]++ == 0) kinds++;
          
           while(kinds > 2)
           {
                //出窗口
                hash[fruits[l]]--;
                if(hash[fruits[l]] == 0) kinds--;
                 l++;
           }
            len = max(len,r - l + 1);
            
            r++;
        }
        return len;
    }
};

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

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

相关文章

【AutoGPT】踩坑帖(follow李鱼皮)

本文写于2024年5月7日 参考视频&#xff1a;AutoGPT傻瓜式使用教程真实体验&#xff01; 对应文章&#xff1a;炸裂的AutoGPT&#xff0c;帮我做了个网站&#xff01; 平台&#xff1a;GitPod 云托管服务 原仓库已经改动很大&#xff0c;应使用的Repo为&#xff1a;Auto-GPT-ZH…

java后端15问!

前言 最近一位粉丝去面试一个中厂&#xff0c;Java后端。他说&#xff0c;好几道题答不上来&#xff0c;于是我帮忙整理了一波答案 G1收集器JVM内存划分对象进入老年代标志你在项目中用到的是哪种收集器&#xff0c;怎么调优的new对象的内存分布局部变量的内存分布Synchroniz…

中职大数据专业介绍:大数据技术应用

近年来&#xff0c;人工智能在经济发展、社会进步、国际政治经济格局等方面已经产生重大而深远的影响。规划纲要对“十四五”及未来十余年我国人工智能的发展目标、核心技术突破、智能化转型与应用&#xff0c;以及保障措施等多个方面都作出了部署。 据2020年全国教育事业发展统…

运用分支结构与循环结构写一个猜拳小游戏

下面我们运用平常所学的知识来写一个小游戏&#xff0c;这样能够加强我们学习的趣味性&#xff0c;并且能够更加的巩固我们所学的知识。 游戏代码&#xff1a; 直接放代码&#xff1a;&#xff08;手势可以使用数字来代替&#xff0c;比如0对应石头&#xff0c;1对应剪刀&…

Qexo:让你的静态博客动起来

Qexo是一个强大而美观的在线静态博客编辑器&#xff0c;它不仅限于编辑&#xff0c;而是将静态博客提升到新的高度。通过GPL3.0开源协议&#xff0c;Qexo提供了一个集编辑、管理、扩展于一体的平台&#xff0c;让静态博客也能拥有动态的元素。无论你是Hexo、Hugo还是Valaxy的用…

【论文阅读】<YOLOP: You Only Look Once for PanopticDriving Perception>

Abstract 全视驾驶感知系统是自动驾驶的重要组成部分。一个高精度的实时感知系统可以帮助车辆在驾驶时做出合理的决策。我们提出了一个全视驾驶感知网络&#xff08;您只需寻找一次全视驾驶感知网络&#xff08;YOLOP&#xff09;&#xff09;&#xff0c;以同时执行交通目标检…

C++类和对象中篇

&#x1f407; &#x1f525;博客主页&#xff1a; 云曦 &#x1f4cb;系列专栏&#xff1a;[C] &#x1f4a8;路漫漫其修远兮 吾将而求索 &#x1f49b; 感谢大家&#x1f44d;点赞 &#x1f60b;关注&#x1f4dd;评论 文章目录 &#x1f4d4;前言&#x1f4d4;1、类的六个…

源代码怎么加密防泄漏?9种方法教会你

想做源代码加密防止泄漏&#xff0c;首先要了解程序员可以通过哪些方式将源代码传输出去&#xff01; 程序员泄密的常见方式 物理方法&#xff1a; — 网线直连&#xff0c;即把网线从墙上插头拔下来&#xff0c;然后和一个非受控电脑直连; — winPE启动&#xff0c;通过光盘…

怎么写毕业论文的? 推荐4个AI工具

写作这件事一直让我们从小学时期就开始头痛&#xff0c;初高中时期800字的作文让我们焦头烂额&#xff0c;一篇作文里用尽了口水话&#xff0c;拼拼凑凑才勉强完成。 大学时期以为可以轻松顺利毕业&#xff0c;结果毕业前的最后一道坎拦住我们的是毕业论文&#xff0c;这玩意不…

常用目标检测算法介绍

目录 1. 常用目标检测算法 2. R-CNN 模型 3. Fast R-CNN 模型 4. Faster R-CNN 模型 5. SSD 模型 1. 常用目标检测算法 在深度学习框架下&#xff0c;目标检测方法通常涉及图像定位和分类两个关键方面。有两种主要的解决方法&#xff1a;一种是一阶&#xff08;one-stage&…

去除快捷方式的箭头图标

文章目录 取消箭头显示恢复箭头显示结果展示 添加快捷方式之后&#xff0c;会有箭头图标&#xff0c;部分场景下看着较为难受&#xff1a; 可以通过如下方式取消/显示箭头&#xff1a; 取消箭头显示 新建一个.bat文件&#xff0c;内部加入如下命令&#xff1a; reg add "…

2024北京市人工智能大模型行业应用分析报告

来源&#xff1a;北京市科学技术委员会 方向一为基于AIGC技术的智能审计合规研究&#xff0c;由北京银行提出&#xff0c;以 提高审计工作效率和准确性为核心目标&#xff0c;需要参赛企业针对检查内容&#xff0c; 利用大模型技术寻找并给出相关现象涉及的制度名称及相关原文…

element ui的确认提示框按钮样式修改

修改确认提示框的默认按钮样式&#xff0c;使用css强制修改 例&#xff1a; js代码&#xff1a; deleteUser(params){this.$confirm("您确定要删除吗&#xff1f;此操作无法撤销并且将永久删除所有数据。", "提示", { type: "warning", cancel…

新款锐科达SV-2402VP SIP广播音频模块18123651365支持RTP流音频广播

一、模块介绍 SV-2402VP网络音频模块是一款通用的独立SIP音频播放模块&#xff0c;其带2*15W功放音频输出&#xff0c;可以轻松地嵌入到OEM产品中。该模块对来自网络的SIP协议及RTP音频流进行解码播放。 该模块支持多种网络协议和音频解码协议&#xff0c;可用于VoIP和IP寻呼…

解决Tomcat日志乱码问题

1、 修改apache-tomcat-10.1.23/conf/server.xml URIEncoding"UTF-8"2、 修改apache-tomcat-10.1.23/conf/logging.properties # java.util.logging.ConsoleHandler.encoding UTF-8 java.util.logging.ConsoleHandler.encoding GBK参考 https://www.jb51.net/ar…

一键接入电商API数据接口京东API通过商品ID、URL采集商品详情页实时数据API接入指南

要一键接入京东电商API数据接口并采集商品详情页的实时数据&#xff0c;您需要按照以下步骤操作&#xff1a; 注册账号&#xff1a;您需要注册一个账号。完成注册后&#xff0c;您将获得用于API认证的ApiKey和ApiSecret。选择API&#xff1a;根据自己的需求选择合适的API服务。…

域控安全 ----> Ntds.dit文件抓取

大家还记得内网渗透的初衷吗&#xff1f;&#xff1f;&#xff1f; 找到域馆&#xff0c;拿下域控&#xff01;&#xff01; 拿下了域控就是拿下了整个域&#xff01;&#xff01; 但是大家知道拿下域环境之后应该怎么操作吗(灵魂拷问)&#xff1f;&#xff1f;&#xff1f; …

科研综述写作技巧:三大要领与实战应用

​在科研工作中&#xff0c;综述不仅是研究者对既有知识体系的梳理与整合&#xff0c;更是为接下来的研究提供方向与思路的重要工具。写好一篇综述&#xff0c;需要掌握三大要领。 要领一&#xff1a;明确目标与定位 在开始综述写作之前&#xff0c;首先要明确综述的目标与定位…

Spring 常用的注入方式有什么?

Spring 是一个非常流行的 Java 开发框架&#xff0c;它提供了多种依赖注入&#xff08;Dependency Injection&#xff09;的方式&#xff0c;使得开发者可以轻松地管理应用程序中的组件依赖关系。在 Spring 中&#xff0c;常用的注入方式主要包括构造器注入、Setter 方法注入、…

全网最全:一文入门最热的LLM应用开发框架LangChain

f#### 1. LangChain 简介 1.1. LangChain 发展史 LangChain 的作者是 Harrison Chase&#xff0c;最初是于 2022 年 10 月开源的一个项目&#xff0c;在 GitHub 上获得大量关注之后迅速转变为一家初创公司。2017 年 Harrison Chase 还在哈佛上大学&#xff0c;如今已是硅谷的…
最新文章