滑动窗口-java

news2024/11/17 11:39:32

主要通过单调队列来解决滑动窗口问题,得到滑动窗口中元素的最大值和最小值。

目录

前言

一、滑动窗口

二、算法思路

1.滑动窗口

 2.算法思路

3.代码详解

三、代码如下

1.代码如下

2.读入数据

3.代码运行结果

总结


前言

主要通过单调队列来解决滑动窗口问题,得到滑动窗口中元素的最大值和最小值。


提示:以下是本篇文章正文内容,下面案例可供参考

一、滑动窗口

给定一个大小为 n≤1000000的数组。

有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 k个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为 [1 3 -1 -3 5 3 6 7],k 为 3。

窗口位置最小值最大值
[1 3 -1] -3 5 3 6 7-13
1 [3 -1 -3] 5 3 6 7-33
1 3 [-1 -3 5] 3 6 7-35
1 3 -1 [-3 5 3] 6 7-35
1 3 -1 -3 [5 3 6] 736
1 3 -1 -3 5 [3 6 7]37

你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数 n 和 k,分别代表数组长度和滑动窗口的长度。

第二行有 n 个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

输入样例:

8 3
1 3 -1 -3 5 3 6 7

输出样例:

-1 -3 -3 -3 3 3
3 3 5 5 6 7

二、算法思路

1.滑动窗口

我们先解释一下滑动窗口,以上述测试样例,滑动窗口的大小为3。

图1.1滑动窗口 

当我们继续遍历元素的时候,为了保证窗口内一直是3个元素,每加入一个元素,就要剔除一个最左边元素,直到遍历到最后一个元素,这就是滑动窗口。

 2.算法思路

图2.1思路模拟 

我们先来求当前滑动窗口的最小值。我们以 图2.1中的滑动窗口为例,求此窗口的最小值从图中可以得到是-3,它前面的3和1是不可能被当作答案输出的;当有两个索引i < j(即i在j的左侧),且存在arr[i] >= arr[j],那么当滑动窗口向右移动,i还在滑动窗口内,那么j一定还在窗口内(由于i在j的左侧所保证的)。因此由于arr[j]的存在,那么arr[i]就一定不会被当作最小值答案输出,那么我们就可以将arr[i]永久移除。

那么我们可以用一个队列来存储还没有被移除的元素的下标,在队列中,这些元素下标按照从小到大的顺序被存储在队列当中,并且有一个特性,保持其中索引对应的元素是单调递增的那么我们当前滑动窗口中最小值的元素就是队列中队头元素对应的数组元素。

当滑动窗口右移时,我们需要把一个新元素放入队列当中。

为了保持队列中的下标对应的元素是单调递增的特性,我们需要将新元素与队尾元素进行比较,如果队尾元素对应的数组元素大于等于新加入的元素,那么我们就可以将队尾元素永久的剔除,将他弹出队列,重复的执行上述操作,直到队列为空或者队尾元素小于新加入的元素。

当然在窗口向右移动的过程中,我们还需要不断地从队列中弹出队头元素,来保证队列中的下标都是滑动窗口中的元素的下标。

3.代码详解

我们引入一位整型数组arr来存储元素,用一维整型数组queue来存储滑动窗口内元素的下标。引入一个整型变量k来表示滑动窗口的长度,用整型变量head表示队头指针,rear表示队尾指针。

通过一个for循环来遍历每个元素,同时我们要来判断此时是否需要弹出队头元素,队尾元素的下标就是此时遍历的元素i,那么队头元素的下标就为 i - k + 1,如果i - k + 1大于队头存储的元素(队列中存储的是元素的下标)即i - k + 1 > queue[head],此时就说明要弹出队头元素来保证队列中的元素个数为k个;然后我们又需要将新加入的元素来与队尾元素对应的数组元素进行比较,如果存在队尾元素对应的数组元素大于等于新加入的元素即arr[queue[rear]] >= arr[i],就说明队尾元素对应的数组元素不可能被当作滑动区间的最小值被输出,就可以将队尾元素弹出,直到队列为空或者队尾元素对应的数组元素小于新加入的元素。接下来将新加入的元素的下标进行入队操作。

最后当滑动窗口中有k个元素的才会输出答案,那么当要输出第一个答案的时候滑动窗口的元素对应的数组下标一定是k-1,后面每加入元素下标肯定是比k-1要大的,故只有下标大于k-1的时候才会输出一个答案,求最小值我们只需要输出一下队头元素对应的数组元素即可。

求滑动窗口的最大值我们只需要重复一下上述操作,将队列中的元素保证为单调递减即可,将新加入的元素与队尾元素对应的数组元素进行比较,如果新加入的元素大于等于队尾元素,那么就说明队尾元素对应的数组元素是小的值,不可能被当作滑动窗口的最大值进行输出,就弹出队尾元素。最后滑动窗口的最大值还是队列中的队头元素对应的数组元素。

三、代码如下

1.代码如下


import java.io.*;
import java.util.*;
public class 滑动窗口 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static int N = 1000010;
    static int[] arr = new int[N];
    //队列里面存的是下标
    static int[] queue = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(br);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int head = 0;
        int rear = -1;
        for(int i = 0;i < n;i++){
            arr[i] = sc.nextInt();
        }
        for(int i = 0;i < n;i++){
            //判断是否弹出队头元素,且每次就弹出一个元素,就写if就可以了
            if (head <= rear && i - k + 1 > queue[head]){
                head++;
            }
            //保证队列中元素的下标对应的元素是一个递增序列,队尾元素大于等于新加入的元素就弹出队尾元素
            while (head <= rear && arr[queue[rear]] >= arr[i]){
                rear--;
            }
            //新元素入队
            queue[++rear] = i;
            //因为这道题是当滑动窗口中有k个元素的话才会输出一个答案,那么第一个答案对应的元素的下标肯定是k-1,后续要输出的答案的元素的下标肯定比k-1大
            if(i >= k-1 ){
                pw.print(arr[queue[head]]+" ");
            }
        }
        pw.println();
        head = 0;
        rear = -1;
        for(int i = 0;i < n;i++){
            if (head <= rear && i - k + 1 > queue[head]){
                head++;
            }
            //保证队列中元素的下标对应的元素是一个递减序列,队尾元素对应的下标元素小于等于新加入的元素就弹出队尾元素
            while (head <= rear && arr[queue[rear]] <= arr[i]){
                rear--;
            }
            //新元素入队
            queue[++rear] = i;
            //因为这道题是当滑动窗口中有k个元素的话才会输出一个答案,那么第一个答案对应的元素的下标肯定是k-1,后续要输出的答案的元素的下标肯定比k-1大
            if(i >= k-1 ){
                pw.print(arr[queue[head]]+" ");
            }
        }
        pw.flush();
    }
}

2.读入数据

8 3
1 3 -1 -3 5 3 6 7

3.代码运行结果

-1 -3 -3 -3 3 3 
3 3 5 5 6 7 

总结

主要我们理解如何保持单调队列中元素的特性,知道如何维护队列即可,这是这道题的关键所在。

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

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

相关文章

(免费领源码)java#SSM#mysql第三方物流系统37852-计算机毕业设计项目选题推荐

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

EasyCode生成的SQL语句中无逗号分隔

EasyCode生成的SQL语句中无逗号分隔 EasyCode是一款非常好用的插件&#xff0c;可以帮助我们生成相关的一些代码&#xff0c;但是在生成SQL对应的xml文件之后&#xff0c;发现语句中多个字段之间没有逗号分隔&#xff0c;而是直接连在了一起。接下来&#xff0c;让我们一起去解…

Kubernetes——Kubectl详解

目录 前言 一、陈述式资源管理方法 二、Kubectl命令操作 1.查 1.1kubectl version——查看版本信息 1.2kubectl api-resources——查看资源对象简写 1.3kubectl cluster-info——查看集群信息 1.4配置Kubectl补全 1.5journalctl -u kubelet -f——查看日志 1.6kubec…

C-数据结构-树状存储基本概念

‘’’ 树状存储基本概念 深度&#xff08;层数&#xff09; 度&#xff08;子树个数&#xff09; 叶子 孩子 兄弟 堂兄弟 二叉树&#xff1a; 满二叉树&#xff1a; 完全二叉树&#xff1a; 存储&#xff1a;顺序&#xff0c;链式 树的遍历&#xff1a;按层遍历&#xff0…

Qt for android 串口库使用

简介 由于Qt for android并没有提供android的串口执行方案&#xff0c;基于需要又懒得自己去造轮子&#xff0c; 使用开源的 usb-serial-for-android 库进行串口访问读写。 如果有自己的需要和库不满足的点&#xff0c;可以查看库的底层调用的Android相关API C/C 串口库 对应…

驱动开发:内核MDL读写进程内存

100编程书屋_孔夫子旧书网 MDL内存读写是最常用的一种读写模式,通常需要附加到指定进程空间内然后调用内存拷贝得到对端内存中的数据,在调用结束后再将其空间释放掉,通过这种方式实现内存读写操作,此种模式的读写操作也是最推荐使用的相比于CR3切换来说,此方式更稳定并不会…

Kruskal算法求最小生成树(加边法)

一、算法逻辑 想要轻松形象理解Kruskal算法的算法逻辑&#xff0c;视频肯定比图文好。 小编看过很多求相关的教学视频&#xff0c;这里选出一个我认为最好理解的这一款安利给大家。 因为他不仅讲解细致&#xff0c;而且还配合了动画演示&#xff0c;可以说把一个抽象的东西讲…

【软件设计师】网络安全

1.网络安全基础信息 网络安全的五个基本要素&#xff1a; 机密性&#xff1a;确保信息不暴露给未授权的实体或进程 完整性&#xff1a;只有得到允许的人才能修改数据&#xff0c;并且能判断出数据是否已被修改 可用性&#xff1a;得到授权的实体在需要时可以访问数据&#xff0…

Web安全:文件上传漏洞详解,文件上传漏洞原理、绕过方式和防御方案。

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

【Mac】 CleanMyMac X for mac V4.15.2中文修复版安装教程

软件介绍 CleanMyMac X是一款为Mac设计的优秀软件&#xff0c;旨在帮助用户优化其设备的性能并提供清理和维护功能。以下是 CleanMyMac X的一些主要功能和特点&#xff1a; 1.系统性能优化&#xff1a;软件可以扫描和修复潜在的性能问题&#xff0c;包括无效的登录项、大文件…

【设计模式】创建型-抽象工厂模式

前言 在软件开发领域&#xff0c;设计模式是一种被广泛接受的解决方案&#xff0c;用于解决特定问题并提供可维护和可扩展的代码结构。抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是其中之一&#xff0c;它提供了一种方法来创建一系列相关或相互依赖的对象…

(三)MobaXterm、VSCode、Pycharm ssh连接服务器并使用

背景&#xff1a;根据前两篇文章操作完成后&#xff0c; 手把手教学&#xff0c;一站式安装ubuntu及配置服务器-CSDN博客 手把手教学&#xff0c;一站式教你实现服务器&#xff08;Ubuntu&#xff09;Anaconda多用户共享-CSDN博客 课题组成员每人都有自己的帐号了&#xff0…

上海亚商投顾:沪指震荡反弹 半导体产业链午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡反弹&#xff0c;尾盘涨幅扩大至1%&#xff0c;深成指、创业板指同步上行&#xff0c;科创50指数…

实时直播技术革新:视频汇聚管理EasyCVR平台助力景区游览体验全面升级

自年初以来&#xff0c;各地文旅热点不断。“温暖驿站”“背诗免票”“王婆说媒”等等&#xff0c;吸引了不少人奔赴远方。2024年在国人消费意愿榜上&#xff0c;旅游又一次占据榜首的位置&#xff0c;有三分之一以上的人&#xff0c;今年会在旅游方面增加消费。中国旅游的发展…

【已解决】./start-base.sh: line 5: $‘\r‘: command not found

问题&#xff1a;在linux下运行启动服务的脚本&#xff0c;提示很多‘\r’不可用。 原因&#xff1a;windows下编辑的文件&#xff0c;放在linux下运行&#xff0c;文件格式有问题&#xff0c;需要转换。 解决方法&#xff1a; 1、用vim编辑器打开文件 vim 文件名 2、进入…

Matplotlib(可视化)小案例

一.认识&#xff1a; Matplotlib是一个Python 2D绘图库&#xff0c;它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形。Matplotlib可用于Python脚本&#xff0c;Python和IPython shell&#xff0c;Jupyter笔记本&#xff0c;Web应用程序服务器和四个图…

K8S-pod资源 探针

一.pod资源限制&#xff1a; 对pod资源限制原因&#xff1a;高并发占用所有的cpu资源、内存资源、会造成雪崩 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 方式&#xff1a; 对pod做…

二叉树的实现(递归实现)

前言&#xff1a;本文讲解通过递归的方式实现二叉树的一些基本接口。 目录 通过左右子树的方式实现二叉树&#xff1a; 二叉树的遍历&#xff1a; 求二叉树结点的个数&#xff1a; 二叉树所有节点的个数&#xff1a; 二叉树叶子节点的个数&#xff1a; 求第k层节点的节点…

学习编程对英语要求高吗?

学习编程并不一定需要高深的英语水平。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 虽然一些编程资源和文档可能…

公务员申论答题稿纸

申论答题稿纸网上不太好找&#xff0c;这里给大家分享两个版本&#xff0c;一个是在PDD上买到的稿纸样式&#xff0c;一种是那种考场答题样式&#xff0c;每个题都给你留有答题位置。第一种合适大家日常练习&#xff0c;比如说练字&#xff0c;第二种就适合答题的时候用了。 …