每日一题——滑动窗口的最大值
滑动窗口的最大值
题目链接
暴力解法
最容易想到的当然还是通过两层循环来暴力求解:一层循环用来移动窗口,一层循环用来在窗口内找到最大值。这种做法的时间复杂度为O(kN)
,会超出时间限制,因此,我们要找到更加高效的方法。
单调队列
注:这种解法建立在单调队列的基础之上,而单调队列是双端队列的特殊形式,如果对单调队列和双端队列还不太了解,建议先看看👉详解单调队列
由于我们要求的是滑动窗口的最大值,那我们不妨先做一个假设:如果当前的滑动窗口中有两个下标i
和j
,其中**i
在j
的左侧(i < j
),并且i
对应的元素不大于j
对应的元素(nums[i] <= nums[j]
)**。
那么我们就可以得到这样一个结论:只要下标i
所代表的元素nums[j]
还在窗口中,那么下标j
所对应的元素nums[j]
也一定在窗口中,且**nums[i]
一定不会是最大值**,也就不会对答案造成影响,我们也就可以将其直接删除了
也可以用一句话来概括:
如果一个数据
val
要进入窗口,那他窗口内所有比它小或等于它的的数都不会对答案造成影响
我们可以用一个队列来存储这些还没有被移除的元素的下标,同时确保从队头到队尾,这些下标是从小到大排列的(保证数据的愿所有顺序),而下标所代表的值是递减排列的,这样队头元素就是滑动窗口的最大值了。
每当窗口向右滑动一个元素,就会有一个新的元素入队。在这个元素入队之前,由于我们要确保队列的单调递减性,因此当队列不为空并且队尾元素小于或等于新的元素时就要通过循环删除这些不会对结果造成影响的元素,最后再把这个元素的下标插入队列。
需要注意:当窗口向右滑动时,最大值下标会离开窗口,永远不会在进入窗口,因此在窗口滑动的过程中,我们要不断比较队首元素的下标(最大值下标)和窗口最左侧的标(下次移动时离开窗口的元素下标),如果离开了窗口,就要将队首元素出队。
例如对于上图的示例:
实现代码
typedef struct DequeNode
{struct DequeNode* next;struct DequeNode* prev;int data;
}DQNode;typedef struct Deque
{DQNode* front;DQNode* tail;
}Deque;void DequeInit(Deque* pq) //双端队列初始化
{assert(pq);pq->front = pq->tail = NULL;
}bool DequeEmpty(Deque* pq) //双端队列判空
{assert(pq);return pq->front == NULL;
}void DequePushTail(Deque* pq, int val) //队尾入队
{DQNode* newNode = (DQNode*)malloc(sizeof(DQNode));newNode->data = val;newNode->next = NULL;newNode->prev = NULL;if (DequeEmpty(pq)){pq->front = pq->tail = newNode;}else{pq->tail->next = newNode;newNode->prev = pq->tail;pq->tail = newNode;}
}void DequePushFront(Deque* pq, int val) //队头入队
{DQNode* newNode = (DQNode*)malloc(sizeof(DQNode));newNode->data = val;newNode->next = NULL;newNode->prev = NULL;if (DequeEmpty(pq)){pq->front = pq->tail = newNode;}else{newNode->next = pq->front;pq->front->prev = newNode;pq->front = newNode;}
}int DequePopFront(Deque* pq) //队头出队
{assert(pq);assert(!DequeEmpty(pq));DQNode* temp = pq->front;int ret = temp->data;pq->front = pq->front->next;if (pq->front == NULL)pq->tail = NULL;elsepq->front->prev = NULL;free(temp);return ret;
}int DequePopTail(Deque* pq) //队尾出队
{assert(pq);assert(!DequeEmpty(pq));DQNode* temp = pq->tail;int ret = temp->data;pq->tail = pq->tail->prev;if (pq->tail == NULL)pq->front = NULL;elsepq->tail->next = NULL;free(temp);return ret;
}int DequeTail(Deque* pq) //取队尾元素
{assert(pq);assert(!DequeEmpty(pq));return pq->tail->data;
}int DequeFront(Deque* pq) //取队头元素
{assert(pq);assert(!DequeEmpty(pq));return pq->front->data;
}void DequeDestroy(Deque* pq) //销毁双端队列
{while (!DequeEmpty(pq)){DQNode* temp = pq->front;pq->front = pq->front->next;free(temp);}free(pq);
}
//-------------------------------------双端队列基本功能实现-----------------------------------------------int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){*returnSize = numsSize - k + 1;int* ret = (int*)malloc(sizeof(int) * (*returnSize));Deque* DQ_Max = (Deque*)malloc(sizeof(Deque)); //用来记录最大值下标DequeInit(DQ_Max); //初始化//先将数组前k个入队列,构建初始窗口for (int i=0; i<k; i++){//队列不为空且队尾元素小于或等于新元素,就将队尾元素删除//确保递减while (!DequeEmpty(DQ_Max) && nums[DequeTail(DQ_Max)] <= nums[i]){DequePopTail(DQ_Max);}DequePushTail (DQ_Max, i); //将下标入队}ret[0] = nums[DequeFront(DQ_Max)]; //初始窗口的最大值就是队头下下标所代表的元素//再将后面剩余的元素下标入队for (int i=k; i<numsSize; i++){//删除不在窗口的下标while (!DequeEmpty(DQ_Max) && DequeFront(DQ_Max) <= i - k)DequePopFront(DQ_Max);//队列不为空且队尾元素小于新元素,就将队尾元素删除//确保非递增while (!DequeEmpty(DQ_Max) && nums[DequeTail(DQ_Max)] <= nums[i]){DequePopTail(DQ_Max);}DequePushTail (DQ_Max, i);//窗口最大值就是队头下下标所代表的元素ret[i - k + 1] = nums[DequeFront(DQ_Max)];}//销毁队列,释放内存DequeDestroy(DQ_Max);return ret;
}
相关文章:

每日一题——滑动窗口的最大值
滑动窗口的最大值 题目链接 暴力解法 最容易想到的当然还是通过两层循环来暴力求解:一层循环用来移动窗口,一层循环用来在窗口内找到最大值。这种做法的时间复杂度为O(kN),会超出时间限制,因此,我们要找到更加高效的…...

【使用go开发区块链】之获取链上数据(03)
上篇文章,我们完成了数据库的连接,本章节,我们将完成ethclient的配置以及初始化 1、ethclient配置 1.1、安装go-ethereum 在命令行终端输入下面代码安装: go get github.com/ethereum/go-ethereum1.2、Ethclient配置 1.2.1、新…...
js 动态设置transformOrigin
transformOrigin属性用于指定元素变换的原点。 // 获取要设置的元素 const element document.getElementById(your-element-id);// 设置transformOrigin属性 element.style.transformOrigin 50% 50%; // 以元素中心为原点// 或者使用变量来设置 const x 0; // x坐标 const …...
docker使用tab无法自动补全命令
本文参考链接 一、安装bash-complete 在线安装 yum install -y bash-completion二、刷新文件 source /usr/share/bash-completion/completions/docker source /usr/share/bash-completion/bash_completion...

既然jmeter也能做接口自动化,为什么还需要pytest自己搭框架?
今天这篇文章呢,我会从以下几个方面来介绍: 1、首先介绍一下pytest框架 2、带大家安装Pytest框架 3、使用pytest框架时需要注意的点 4、pytest的运行方式 5、pytest框架中常用的插件 一、pytest框架介绍 pytest 是 python 的第三方单元测试框架&a…...
Objective-C获取变量类型的方法
在Objective-C中,要获取一个对象的类型,可以使用[object class]方法。这将返回一个Class对象,表示该对象的类型。 另外,typeid是C中的关键字,用于获取一个变量的类型信息。在Objective-C中,typeid并不适用于…...
相机可见区域,使用鼠标拖拽模型
知识点 向量射线检测坐标转换 思路 使用射线检测获取射线检测点与模型对象之间的偏移量 (世界空间)使用相机的坐标转换获取检测点与鼠标位置之间的偏移量 (屏幕空间)拖拽时,更新模型位置 代码示例 using UnityEng…...
Vue 2 与 Vue 3 的全面比较
Vue 2 与 Vue 3 的全面比较 1. 性能提升 Vue 3 的性能得到了显著提升。虚拟 DOM 已经重写,使补丁过程更快。 对比: Vue 3 使用了基于 Proxy 的新观察者机制,取代了 Vue 2 的基于 Object.defineProperty 的观察者。 Object.definePropert…...
Unity学习笔记--如何优雅简便地利用对象池生成游戏对象(进阶版)LRU + 对象池
前言 之前写过一篇关于对象池的文章,现在来看写的并不是很好,所以来考虑优化下。 现在来看一年前写的代码,越看越不能入目hhh Unity学习笔记–如何优雅简便地利用对象池生成游戏对象 前置知识 Unity学习笔记–使用 C# 开发一个 LRU 代码实…...

【Spring专题】Bean的声明周期流程图
前言 我向来不主张【通过源码】理解业务,因为每个人的能力有限,甚至可能会因为阅读错误导致出现理解上的偏差,所以我决定,还是先帮大家【开天眼】,先整体看看流程图,好知道,Spring在写源码的过…...

C++实现俄罗斯方块(源码+详解)
👂 Take me Hand Acoustic - Ccile Corbel - 单曲 - 网易云音乐 源码Debug工具 (1)cppreference.com (主) (2)必应 (bing.com) (3)GPT(主) &#…...

01:STM32点灯大师和蜂鸣器
目录 一:点亮1个LED 1:连接图 2:函数介绍 3:点灯代码 二:LED闪烁 1:函数介绍 2:闪烁代码 三:LED流水灯 1:连接图 2:函数介绍 3:流水灯代码 四:蜂鸣器 1:连接图 2:蜂鸣器代码 一:点亮1个LED 1:连接图 因为IO口与LED负极相连所以IO口输出低电频,点亮LED (采用的是低…...

linux pwn 基础知识
环境搭建 虚拟机安装 镜像下载网站为了避免环境问题建议 22.04 ,20.04,18.04,16.04 等常见版本 ubuntu 虚拟机环境各准备一份。注意定期更新快照以防意外。虚拟机建议硬盘 256 G 以上,内存也尽量大一些。硬盘大小只是上界&#…...
Unity Poisson分布 【由ChatGPT生成】
Unity Poisson分布 【由ChatGPT生成】 前言项目Unity场景布置代码编写添加并设置脚本运行效果总结 前言 在Unity游戏开发中,数学和统计学的概念常常用于解决各种问题,从资源分配到游戏机制的设计。本文将探讨Poisson分布在Unity游戏开发中的实际应用和作…...
permission denied while trying to connect to the Docker daemon socket 错误
安装 docker 执行错误如下: $ docker pspermission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get “http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json”: dial unix /var/run/docker.sock: connect:…...
pytorch nn.ModuleList和nn.Sequential的用法笔记
有部分内容转自: pytorch小记:nn.ModuleList和nn.Sequential的用法以及区别_慕思侣的博客-CSDN博客 但是有部分内容做了修改调整, 在构建网络的时候,pytorch有一些基础概念很重要,比如nn.Module,nn.ModuleList,nn.Sequential,这些类我们称为为容器(containers),可…...

SQL | 高级数据过滤
5-高级数据过滤 通过组合WHERE子句,建立功能更强的检索语句。 5.1-组合WHERE子句 前面写的都是单一条件下的WHERE子句,SQL语句允许给出多个WHERE子句来组合检索,这些WHERE子句通过AND子句或者OR子句进行连接。 操作符(operato…...
ARM架构银河麒麟docker,源码编译安装GDAL
docker中安装依赖 sudo apt-get update sudo apt-get install build-essential autoconf automake libtool sudo apt-get install libproj-dev libgeos-dev libjson-c-dev libpng-dev libjpeg-dev sudo apt-get install python3-dev sudo apt-get install python3.11-dev去官网…...
(3)原神角色数据分析-3
绘图类 在名为“WRITEPHOT.py”的文件中,定义如下绘图方式,则在主页面(app.py)文件中,可通过如下方式调用: from WRITEPHOTO import WriteScatter,WriteFunnel,WriteBarData,WritePie,WriteLineBar 代码如下: "…...

skywalking日志收集
文章目录 一、介绍二、添加依赖三、修改日志配置1. 添加链路表示traceId2. 添加链路上下文3. 异步日志 四、收集链路日志 一、介绍 在上一篇文章skywalking全链路追踪中我们介绍了在微服务项目中使用skywalking进行服务调用链路的追踪。 本文在全链路追踪的基础上,…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...