滑动窗口详解

2023-05-16

前言

滑动窗口是双指针的一种特例,可以称为左右指针,在任意时刻,只有一个指针运动,而另一个保持静止。滑动窗口路一般用于解决特定的序列中符合条件的连续的子序列的问题。

滑动窗口的时间复杂度是线性的,一般为 O ( n ) O(n) O(n),滑动窗口的左右边界都不会向左滑动,向左滑动等于走回头路,是一种回溯的算法,很可能会陷入死循环。
滑动窗口是一种全遍历问题,一定会遍历到末尾的。
本质思路在于:

  1. 初始化将滑动窗口压满,取得第一个滑动窗口的目标值
  2. 继续滑动窗口,每往前滑动一次,需要删除一个和添加一个元素,求最优的目标值

滑动窗口所解决的问题类型

一般来说,我们面对的最多的两个序列就是数组与字符串。
那么,滑动窗口解决的就是子序列子数组的问题。

  1. 字符串类的滑动窗口问题
    这类问题一般可以分为两类,单个字符串;两个字符串。两个字符串当中又可以按照连续序列与非连续序列进行划分。
    对于两个字符串而言,一般是一个字符串作为母体,另一个字符串作为比较。
    举几个力扣中题目的例子:
    🅰️字符串的最小覆盖字串(非连续序列)
    🅰️字符串的排列(连续序列)
    🅰️字符串的所有字母异位词(连续序列)
    🅰️无重复字符的最长子串(单个字符串)
    🅰️最多包含连个重复字符的最长字串
    🅰️最多包含k个重复字符的最长字串
    字符串的最小覆盖字串题目为例
    最小覆盖字串

对于字符串而言,两个字符串问题的滑动窗口的具体代码如下

//母字符串s,匹配字符串p
Map<Character,Integer> window=new HashMap<>();
Map<Character,Integer> need=new HashMap<>();
int left=0;
int right=0;
int len=Integer.MAX_VALUE;
char [] array=s.toCharArray();
//将匹配字符串p放入Map中去
for(int i=0;i<p.length();i++)
{
	need.put(p.charAt(i),need.getOrDefault(p.charAt(i),0)+1);
}
while(right<s.length())
{
	char c=array[right];
	right++;
	//依据
	if(need.containsKey(c))
	{
		//window遍历了所有的从left到right的值
		//很可能这些值中的某个字符多了,因为需要包含p的所有字符
		windows.put(c,window.getOrDefault(c,0)+1);
		//这时候就要思考多种情况的出现
		//不能need中一包含这个字符,我就进行valid++
		//可能在字符串p中这个字符是重复的,有多个,所以
		//需要记录字符的个数,这也是为什么用Map的原因
		if(window.get(c).equals(need.get(c)))
		{
			valid++;
		}
	}
	//什么时候进行窗口的更新
	//满足基本条件
	//什么叫满足基本条件
	//比如说最短覆盖字串,我们就要满足覆盖这个基本条件
	//但是这个时候的覆盖可能不是最短的
	//所以我们通过缩小左边框来进行最小的判断。

	//注意下面是通过need的长度而不是p的长度来判断。
	//p中可能有很多重复的字符
	//你要注意上面valid进行一次更新是不容易的,
	//所有重复的都进入windowz这个窗口,我才能加一次
	while(valid==need.size())
	{
		char d=array[left];
		//你要想清楚,什么时候进行你想要的数据的提领
		//因为left,可能下一次你最基本的条件都不能保证
		//所以这时候,我就要进行记录
		//这时候进行思考,怎么样最小
		//我们一般常见的作法是什么,循环比较,设置一个最大值
		//然后不断比较
		if(right-left<len)
		{
			start=left;
			//注意right++与left++什么时候做对于你下面的
			//len需不需要减1加1至关重要
			len=right-left;
		}
		left++;
		if(need.containsKey(d))
		{
			//注意下方的顺序问题
			//一定要在前面进行判断,后面削减
			if(window.get(d).equals(need.get(d)))
			{
				valid--;
			}
			window.put(d,window.getOrDefault(d,0)-1);
		}
	}
}
return s.substring(start,start+len);

再来看一道题,并且思考滑动窗口的优化问题
无重复字符的最长字串
无重复字符的最长字串
这道题可以直接套用我们的模板

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //需要window这个hashmap来比较数据
        //这道题考虑的是字串的问题,比较麻烦,字串必须是连续的
        //如果考虑的是子序列的问题,这题就比较简单,直接使用可以去重的一类数据结构拿住所有的不重复字符就行
        Map<Character,Integer> window=new HashMap<>();
        //这道题你要想清楚的是你控制整个
        char []array=s.toCharArray();
        int left=0;
        int right=0;
        int valid=0;
        int len=0;
        int start=0;
        int sons=0;
        while(right<s.length())
        {
            char c=array[right];
            window.put(c,window.getOrDefault(c,0)+1);
            right++;
            while(window.get(c)>1)
            {
                //这时候不能直接更新结果,你已经大于1了
                char d=array[left];
                window.put(d,window.getOrDefault(d,0)-1);
                left++;
            }
            //我觉得在这里记录结果不太好,每一次都要更新,其实是没有必要的
            //已阅,狗屁不通,不放在这里,难道放在内循环里,没有重复的都不要?
            // len=len>right-left?len:right-left;
            if(len<right-left)
            {
                len=right-left;
                start=left;
            }
        }
        return len;
    }
}

但是这里分析一种情况,当s="abddd"的情况时,模板中是利用不断删减’a’,‘b’,‘d’,其实直接定位到第一个‘d’字符是最好的,来看这一种解法

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s.length()==0) return 0;
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        int max = 0;
        int left = 0;
        for(int i = 0; i < s.length(); i ++){
            if(map.containsKey(s.charAt(i))){
                left = Math.max(left,map.get(s.charAt(i)) + 1);
            }
            map.put(s.charAt(i),i);
            max = Math.max(max,i-left+1);
        }
        return max;
    }
}
  1. 数组类的滑动窗口问题
    🅰️ 长度最小的子数组
    🅰️ 滑动窗口的最大值
    🅰️和为s的连续正数序列
    🅰️子数组最大平均数
    上面的每一种题目,相对于字符串的问题来说更加简单,有时候甚至不需要进行哈希集合的定义,而只需要进行简单的这个左右指针的移动,维护好窗口就行。

滑动窗口的技巧

使用滑动窗口的难点在于:什么时候应该移动右侧指针来扩大窗口,什么时候移动左侧指针来减小窗口。
我们来分析一下上面说的滑动窗口的最大值
滑动窗口
这道题有一个额外的附加条件:滑动窗口的大小为k,这就可以称为我们缩小窗口的依据,从而方便的利用滑动窗口来解题。
我们在看一道题,最大子数组和
最大子数组和
这道题几乎与前面的滑动窗口最大值类似,只不过题目中没有显式的提出缩小窗口的条件,需要我们自己去寻找。

class Solution
{
	public int maxSubArray(int[] nums) {
		int left=0;
		int right=0;
		int sum=0;
		int maxsum=nums[0];
		while(right<nums.length())
		{
			sum+=nums[right];
			if(sum<0)
			{
				sum-=nums[left];
				left++;
			}
			//进行答案的更新
			maxsum=Math.max(maxsum,sum);
		}
		//进行特殊情况的处理
		        int maxVal = nums[0];
        for (int i = 1; i <nums.size(); i++) {
            maxVal = max(maxVal, nums[i]); 
        }
        return maxVal < 0 ? maxVal : maxsum;
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

滑动窗口详解 的相关文章

  • UCOS开发手册中关于OSQPend()函数讲

    转自 xff1a http www openedv com thread 44168 1 1 html UCOS开发手册中 第十章 UCOSIII消息传递 章节中关于等待消息队列的函数OSQPend 讲解有误 xff0c OSQPend 函
  • ucos-ii学习笔记——信号量集(事件标志组)的原理及使用

    xfeff xfeff ucos ii学习笔记 信号量集 事件标志组 的原理及使用 Created on 2012 10 8 Author zhang bin 学习笔记 for ucos ii PC redesigned by zhang
  • 低速容错CAN:ISO 11898-3 与ISO 11519-2标准两者关系

    xfeff xfeff 有关 低速容错CAN xff1a ISO 11898 3 与ISO 11519 2标准两者关系 最近有几个客户问到这个问题 xff0c 对应的产品是否兼容 于是上ISO官网查看发现并无两者的关系 xff0c 不过在网
  • CAN总线仲裁机制--对于多个节点同时发送相同ID的报文

    最近在学习CAN总线 xff0c 原先一直不太明白 xff0c 若有A xff0c B 2个节点同一时刻一起向总线上发送数据 xff0c CAN总线是怎么仲裁的 xff0c 来让A xff0c B其中一个节点退出 xff0c 保证高优先级的
  • roslaunch mavros px4.launch fcu_url=xxxx到底做了什么

    roslaunch mavros px4 launch fcu url 61 xxxx到底做了什么 一言以蔽之 xff0c roslaunch mavros px4 launch fcu url span class token opera
  • PX4,ROS,gazebo仿真

    https gitee com bingobinlw some tree master Overview Simulation Px4 command Slam map image process planning P200 AmovCar
  • 飞行控制PID算法——无人机飞控

    PID控制应该算是应用非常广泛的控制算法了 小到控制一个元件的温度 xff0c 大到控制无人机的飞行姿态和飞行速度等等 xff0c 都可以使用PID控制 这里我们从原理上来理解PID控制 PID proportion integration
  • Ubuntu20.04桌面版图文安装(超详细)

    Ubuntu20 04桌面版图文安装 xff08 超详细 xff09 一 准备工具 VMWare Workstation15 Pro xff1b ubuntu 20 04 desktop amd64 iso xff1b 二 虚拟机初始配置
  • 嵌入式芯片概念梳理 - CPU、MCU、MP、DSP、FPGA、ASIC

    CPU中央处理单元包含基本的运算单元AUL xff0c 存储单元cache等基本资源 xff0c 实现硬件设备的基本控制功能 中央处理器作为一个普世概念 xff0c 实际根据具体数据处理功能方向不同 xff0c 细分位DSP MCU和MP
  • UART、I2C、USB、SPI、CAN、Jtag、PCI/PCIE协议汇总

    协议通信方式UART串行全双工I2C SPI是串行外设接口 xff08 Serial Peripheral Interface xff09 的缩写 SPI是一种高速的 全双工 同步的通信总线 xff0c 并且在芯片的管脚上只占用四根线 xf
  • busybox概述

    busybox是什么 xff1f xff08 1 xff09 busybox是Linux上的一个应用程序 application xff0c 即只有一个ELF文件头 xff08 2 xff09 它整合了许多Linux上常用的工具和命令 xf
  • SR-IOV

    SSR IOV是Single Root I O Virtualization的缩写 在虚拟机中 xff0c 一切皆虚拟 比如网卡 xff0c 虚拟机看来好像有一个真实网卡 xff0c 但是这个网卡是宿主机虚拟出来的硬件 xff0c 也就是一
  • 希尔排序算法

    本章介绍排序算法中的希尔排序 内容包括 xff1a 1 希尔排序介绍 2 希尔排序图文说明 3 希尔排序的时间复杂度和稳定性 4 希尔排序实现 4 1 希尔排序C实现 4 2 希尔排序C 43 43 实现 4 3 希尔排序Java实现 转载
  • 归并排序算法

    概要 本章介绍排序算法中的归并排序 内容包括 xff1a 1 归并排序介绍 2 归并排序图文说明 3 归并排序的时间复杂度和稳定性 4 归并排序实现 4 1 归并排序C实现 4 2 归并排序C 43 43 实现 4 3 归并排序Java实现
  • 拓扑排序算法

    拓扑排序介绍 拓扑排序 Topological Order 是指 xff0c 将一个有向无环图 Directed Acyclic Graph简称DAG 进行排序进而得到一个有序的线性序列 这样说 xff0c 可能理解起来比较抽象 下面通过简
  • 线性时不变系统输出调节问题

    线性时不变系统输出调节问题 最近在学习 Nonlinear output regulation 中的linear output regulation时 xff0c 对于linear robust output regulation的问题时
  • MinGW-w64安装教程——著名C/C++编译器GCC的Windows版本

    MinGW w64安装教程 著名C C 43 43 编译器GCC的Windows版本 MinGW w64安装教程 著名C C 43 43 编译器GCC的Windows版本 本文主要讲述如何安装 C语言 编译器 MinGW w64 xff0c
  • RT-Thread实时操作系统简介

    目录 一 概述 二 架构 三 版本选择 四 内核启动流程 五 自动初始化机制 六 内核对象模型 七 I O设备模型 1 框架 2 设备驱动使用序列图 3 设备类型 八 FinSH控制台 九 ENV工具 1 menuconfig 2 Scon
  • PCIe RAS

    对于Linux系统针对RAS的AER错误处理机制完成 PCIe RAS简单来讲就是PCIe的错误检测 纠正以及汇报的机制 它可以方便我们准确的定位 xff0c 纠正和分析错误增强系统的健壮性和可靠性 PCIe错误的分类 PCIe错误分为可校

随机推荐

  • Linux下的regulator调试

    先看regulator使用的小demo 如 i2c8 touchscreen 64 28 vddcama supply 61 lt amp xxxxx gt int ret struct regulator power static int
  • 关于添加系统调用遇到 Unable to handle kernel paging request at virtual address 的解决

    Unable to handle kernel paging request at virtual address 是内存访问异常的错误 xff0c 原因通常有三种 xff1a virtual address 为 0x00000000 时
  • vscode安装配置clang-format插件及使用

    vscode安装配置clang format插件及使用 首先安装插件 在vscode扩展里搜索clang format xff0c 安装排名第一的xaver clang format 确认clang format可执行程序路径 window
  • 简历中项目描述怎么写啊

    http wenda tianya cn question 7ade6dc9324bed88
  • 树莓派(Raspberry Pi 3) - 系统烧录及系统使用

    树莓派 xff08 Raspberry pi xff09 是一块集成度极高的ARM开发板 xff0c 不仅包含了HDMI xff0c RCA xff0c CSI xff0c HDMI xff0c GPIO等端口 xff0c 还支持蓝牙以及无
  • flashcache原理

    介绍flashcache的文章很多 xff0c 我就不废话了 使用上 xff0c 有余峰老哥的 文章 xff1b 原理上 xff0c 有ningoo同学的 flashcache系列 但是ningoo同学漏掉了device mapper和fl
  • 无人机算法之PID

    xff08 未完成 xff09 一 PID介绍 xff08 百度百科 xff09 PID 控制器 xff08 比例 积分 微分控制器 xff09 是一个在工业控制应用中常见的反馈回路部件 xff0c 由比例单元 P 积分单元 I 和微分单元
  • java:接口、lambda表达式与内部类

    接口 xff08 interface 接口用来描述类应该做什么 xff0c 而不指定他们具体应该如何做 接口不是类 xff0c 而是对符合这个接口的类的一组需求 接口定义的关键词是interface span class token key
  • 卫星系统算法课程设计 - 第二部分 qt的安装与创建项目

    上一篇文章只讲了基本的东西 xff0c 这一篇要完成qt的安装 xff0c 构建项目 xff0c 并且将上一篇的代码导入进去 某比利比例搜qt安装 xff0c 看到qt5 14 2的下载安装 xff0c 跟着做 1 创建项目 创建新项目 x
  • 无人机-材料准备

    xff08 未完成 xff09 一 使用空心杯电机 xff0c 型号8520 xff0c 1S版本 xff0c 约5G每只 二 空心杯机架 xff0c 型号QX90 xff0c 约8 5g 三 使用55MM桨 四 1S 600MA电池 五
  • CMake中链接库的顺序问题

    原文链接 xff1a https blog csdn net lifemap article details 7586363 cmake中链接库的顺序是a依赖b xff0c 那么b放在a的后面 例如进程test依赖a库 b库 a库又依赖b
  • 鸿蒙wifi Demo运行

    title 鸿蒙Wi Fi Demo运行 date 2021 1 1 22 25 10 categories harmony 本文首发于LHM s notes 欢迎关注我的博客 坑有点多 由于之前没有看过wifi的内核态代码 xff0c 所
  • 将TensorFlow训练好的模型迁移到Android APP上(TensorFlowLite)

    将TensorFlow训练好的模型迁移到Android APP上 xff08 TensorFlowLite xff09 1 写在前面 最近在做一个数字手势识别的APP xff08 关于这个项目 xff0c 我会再写一篇博客仔细介绍 xff0
  • 汉诺塔代码图文详解(递归入门)

    游戏规则 xff1a 已知条件存在A B C三根柱子 xff0c A上套有N片圆盘 如下图 目的将A上的所有圆盘移到C上约束条件每次只能移动一片圆盘 xff0c 且整个过程中只能出现小圆盘在大圆盘之上的情况 首先我们模拟 N 61 2 xf
  • STM32 最小系统电路简析

    文章目录 一 最小系统的组成1 供电电路2 外部晶振3 BOOT选择4 复位电路 二 最小系统实例1 STM32F103C8T6最小系统 三 各部分组成简析1 供电电路设计2 外部晶振原理3 BOOT设计4 复位电路设计 一 最小系统的组成
  • 带参数的宏的问题

    include 34 iostream 34 using namespace std define COMPUTE XX a a a 43 a 2 int main int a 61 2 int test1 61 COMPUTE XX 43
  • python_imbalanced-learn非平衡学习包_02_Over-sampling过采样

    python imbalanced learn非平衡学习包 01 简介 python imbalanced learn非平衡学习包 02 Over sampling过采样 后续章节待定 希望各位认可前面已更 您的认可是我的动力 Over s
  • TX2+JetPack3.2.1+opencv3.3.1+caffe+realsense2.0环境配置教程

    TX2 开箱 一共6样 xff0c 开机之后自带ubuntu16 04LTS的系统 xff0c ARMv8的处理器 xff0c 所以有些指令 xff0c 安装包必须与arm结构保持一致 开机之后 xff0c 按照指示进入图形界面 xff1a
  • 初视openwrt

    openwrt是一个微型的嵌入式操作系统 在编译的时候需要安装许多的工具和库 预置环境 xff1a sudo apt get install g 43 43 libncurses5 dev zlib1g dev bison flex unz
  • 滑动窗口详解

    前言 滑动窗口是双指针的一种特例 xff0c 可以称为左右指针 xff0c 在任意时刻 xff0c 只有一个指针运动 xff0c 而另一个保持静止 滑动窗口路一般用于解决特定的序列中符合条件的连续的子序列的问题 滑动窗口的时间复杂度是线性的