滑动窗口-java

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

目录

前言

一、滑动窗口

二、算法思路

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.mzph.cn/news/842753.shtml

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

相关文章

Leetcode刷题笔记5

76. 最小覆盖子串 76. 最小覆盖子串 - 力扣&#xff08;LeetCode&#xff09; 解法一&#xff1a; 暴力枚举 哈希表 先定义left和right&#xff0c;可以在随机位置 枚举一个位置向后找&#xff0c;找到一个位置之后&#xff0c;发现这段区间是一个最小的区间之后&#xff0c…

【探索数据之美】“从基础到精通——深入解析数据结构与二叉树的秘密“

gitee代码获取链接&#xff1a;https://gitee.com/flying-wolf-loves-learning/data-structure.git 一、树的概念 1.1 概念简述 数据结构中的树是一种层次结构&#xff0c;它由节点&#xff08;node&#xff09;和边&#xff08;edge&#xff09;组成。每个节点都有零个或多…

解决鼠标滚动时element-ui下拉框错位的问题

问题描述&#xff1a;elementUi的el-select下拉选择框,打开之后,直到失去焦点才会自动关闭。 在有滚动条的弹窗中使用时就会出现打开下拉框,滚动弹窗,el-select下拉框会超出弹窗范围的问题. 解决方案&#xff1a; 1、先在util文件夹下创建个hideSelect.js文件&#xff0c;代码…

数据结构(六)队列

文章目录 一、概念二、逻辑结构&#xff1a;线性结构三、存储结构&#xff08;一&#xff09;顺序队列&#xff08;二&#xff09;循环队列1. 结构体定义2. 创建队列&#xff08;1&#xff09;函数定义&#xff08;2&#xff09;注意点&#xff08;3&#xff09;代码实现 3. 入…

改进rust代码的35种具体方法-类型(十九)-避免使用反射

上一篇文章 从其他语言来到Rust的程序员通常习惯于将反思作为工具箱中的工具。他们可能会浪费很多时间试图在Rust中实现基于反射的设计&#xff0c;却发现他们所尝试的事情只能做得不好&#xff0c;如果有的话。这个项目希望通过描述Rust在反思方面做什么和不做什么&#xff0c…

C语言例题47、从键盘输入一个正整数n,计算1+1/(1+2)+1/(1+2+3)+…+1/(1+2+3+…+n) 的值

#include <stdio.h>void main() {int x;int fm 0;//分母double sum 0;printf("请输入一个正整数&#xff1a;");scanf("%d", &x);for (int i 1; i < x; i) {fm i;//分母变化sum sum 1.0 / fm;if (i ! x) {printf("1/%d ", f…

【Linux】升级GCC(版本9.3),补充:binutils

GCC&#xff1a;GNU Compiler Collection 。编译器&#xff0c;几乎Linux中所有程序&#xff08;包括内核&#xff09;都是gcc编译的&#xff0c;包括libc。 gcc不仅仅是编译器&#xff0c;gcc也有很多库&#xff0c;依赖libc。gcc和libc互相依赖。 GCC官网&#xff1a;GCC, …

【C++练级之路】【Lv.22】C++11——右值引用和移动语义

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、右值引用1.1 左值和右值1.2 左值引用和右值引用的范围1.3 左值引用的意义 二、移动语义2.1 移动构造…

AI大模型探索之路-实战篇9:探究Agent智能数据分析平台的架构与功能

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…

中断处理过程介绍

概念 中断 中断源 分类 中断处理过程 中断请求 实现器件 中断判优 软件判优 过程 器件实现 程序实现 硬件判优 链路判优 器件实现 控制器判优 中断响应 中断服务 中断返回

STM32H750外设之ADC通道选择

目录 概述 1 通道选择功能介绍 2 通道选择&#xff08; SQRx、 JSQRx&#xff09; 2.1 通道复用 2.1.1 通道介绍 2.1.2 通道框图 2.2 转换分组 2.3 内部专用通道 3 通道预选寄存器 (ADCx_PCSEL) 3.1 功能介绍 3.2 预选通道寄存器 概述 本位主要介绍STM32H750外设之…

栈 队列

目录 1.1栈的基本概念 1.1.1栈的定义 1.1.2栈的基本操作 1.2栈的顺序存储结构 1.2.1构造原理 1.2.2基本算法 1.3栈的链式存储结构 1.3.1构造原理 1.3.2基本算法 2.1队列的基本概念 2.1.1队列的定义 2.1.2队列的基本运算 2.2队列的顺序存储结构 2.2.1构造原理 2.2.1基…

CRLF注入漏洞

1.CRLF注入漏洞原理 Nginx会将 $uri进行解码&#xff0c;导致传入%0a%0d即可引入换行符&#xff0c;造成CRLF注入漏洞。 执行xss语句 2.漏洞扩展 CRLF 指的是回车符(CR&#xff0c;ASCII 13&#xff0c;\r&#xff0c;%0d) 和换行符(LF&#xff0c;ASCII 10&#xff0c;\n&am…

FTP协议——LightFTP安装(Linux)

1、简介 LightFTP是一个轻量级的FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;客户端软件。FTP是一种用于在网络上传输文件的标准协议&#xff0c;允许用户通过TCP/IP网络&#xff08;如互联网&#xff09;在计算机之间进行文件传输。 2、步骤…

在ARM开发板上,栈大小设置为2MB(常用设置)里面存放的数据

系列文章目录 在ARM开发板上&#xff0c;栈大小设置为2MB&#xff08;常用设置&#xff09;里面存放的数据 在ARM开发板上&#xff0c;栈大小设置为2MB&#xff08;常用设置&#xff09;里面存放的数据 系列文章目录 在ARM开发板上&#xff0c;栈&#xff08;Stack&#xff09;…

Thingsboard规则链:Message Type Filter节点详解

一、Message Type Filter节点概述 二、具体作用 三、使用教程 四、源码浅析 五、应用场景与案例 智能家居自动化 工业设备监控 智慧城市基础设施管理 六、结语 在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据处理与自动化流程的实现是构建智能系统的关键。作…

创新实训2024.05.28日志:记忆化机制、基于MTPE与CoT技术的混合LLM对话机制

1. 带有记忆的会话 1.1. 查询会话历史记录 在利用大模型自身能力进行对话与解答时&#xff0c;最好对用户当前会话的历史记录进行还原&#xff0c;大模型能够更好地联系上下文进行解答。 在langchain chat chat的chat函数中&#xff0c;通过实现langchain框架提供的ChatMemo…

【设计模式】创建型-工厂方法模式

前言 工厂方法模式是一种经典的创建型设计模式&#xff0c;它提供了一种灵活的方式来创建对象实例。通过本文&#xff0c;我们将深入探讨工厂方法模式的概念、结构和应用。 一、什么是工厂方法模式 工厂方法模式是一种创建型设计模式&#xff0c;旨在解决对象的创建过程和客…

Parquet使用指南:一个超越CSV、提升数据处理效率的存储格式

前言 在大数据时代&#xff0c;数据存储和处理的效率越来越重要。同时&#xff0c;我们在工作中处理的数据也越来越多&#xff0c;从excel格式到csv格式&#xff0c;从文件文档传输到直接从数据库提取&#xff0c;数据单位也从K到M再到G。 当数据量达到了G以上&#xff0c;几…

ROS | 自动导航

保存&加载地图&#xff1a; image:地图文件 resolution:地图分辨率&#xff08;珊格地图&#xff09; origin&#xff1a;地图左下标 第三个参数是偏转角度 加载创建好的yaml文件&#xff1a; 年轻人第一次导航&#xff1a; 全局规划器&#xff1a; 代价地图设置参数&#…