【二叉树】【单调双向队列】LeetCode239:滑动窗口最大值
作者推荐
map|动态规划|单调栈|LeetCode975:奇偶跳
涉及知识点
单调双向队列 二叉树
题目
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1
输出:[1]
参数范围:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
单调栈
时间复杂度😮(n)。
queMax中记录(i-k,i],如果i1 < i2,且nums[i1] <=nums[i2],那么i1无论如何都无法成为最大值。故可以淘汰i1,淘汰i1后,成降序排列。队首元素最大。
对queMax有三种操作。
| 操作一 | 队尾淘汰i1 |
| 操作二 | 队尾插入i2 |
| 操作三 | 队首删除i-k,由于操作二,queMax不会为空,所以无需判断是否为空。如果i-k已经被操作一淘汰,则不能删除。 |
代码
核心代码
class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int i = 0;std::deque<int> queMax;vector<int> vRet;for ( i = 0; i < k; i++){while (queMax.size() && (nums[queMax.back()] <= nums[i])){queMax.pop_back();}queMax.emplace_back(i); }vRet.emplace_back(nums[queMax.front()]);for (; i < nums.size(); i++){if (i - k == queMax.front()){queMax.pop_front();}while (queMax.size() && (nums[queMax.back()] <= nums[i])){queMax.pop_back();}queMax.emplace_back(i);vRet.emplace_back(nums[queMax.front()]);}return vRet;}
};
测试用例
template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}
}int main()
{vector<int> nums;int k;{Solution sln;nums = { 1, 3, -1, -3, 5, 3, 6, 7 }, k = 3;auto res = sln.maxSlidingWindow(nums, k);Assert(vector<int>{ 3,3,5,5,6,7 }, res);}{Solution sln;nums = { 1 }, k = 1;auto res = sln.maxSlidingWindow(nums, k);Assert(vector<int>{ 1 }, res);}//CConsole::Out(res);
}
2023年3月二叉树
用多键二叉树(红黑树)mulset记录滑动窗口中的数,由于二叉树默认是升序排列,所以最后一个元素,就是最大值。由于二叉树的插入、删除的时间复杂度是O(logn),故总时间复杂度是O(nlogn) 。
class Solution {public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int i = 0;std::multiset<int> setNums;for (; i + 1 < k; i++){setNums.insert(nums[i]);}vector<int> vRet;for (; i < nums.size(); i++){setNums.insert(nums[i]);vRet.push_back(*setNums.rbegin());auto it = setNums.find(nums[i + 1 - k]);setNums.erase(it);}return vRet;}};
2023年3月第二版
class Solution {
public:
vector maxSlidingWindow(vector& nums, int k) {
vector<pair<int, int>> vValueIndex;
vector vRet;
int iPos = 0;
for (int i = 0; i < nums.size(); i++)
{
while ( ( vValueIndex.size() > iPos ) && (nums[i] >= vValueIndex.back().first))
{
vValueIndex.pop_back();
}
vValueIndex.emplace_back(nums[i], i);
if (i + 1 >= k)
{
vRet.push_back(vValueIndex[iPos].first);
}
if (i + 1 - k == vValueIndex[iPos].second)
{
iPos++;
}
}
return vRet;
}
};
2023年8月版
class Solution{
public:
vector maxSlidingWindow(vector&nums, int k) {
m_c = nums.size();
//每k个元素用一组,vLeft各元素到组首的最大值,vRight各元素到组尾的最大值
vector vLeft(m_c), vRight(m_c);
int iMax = 0;
for (int i = 0; i < m_c; i++)
{
if (0 == i % k)
{
iMax = nums[i];
}
else
{
iMax = max(iMax, nums[i]);
}
vLeft[i] = iMax;
}
iMax = -100 * 1000;
for (int i = m_c-1;i >= 0 ; i-- )
{
if (0 == (i+1) % k)
{
iMax = nums[i];
}
else
{
iMax = max(iMax, nums[i]);
}
vRight[i] = iMax;
}
vector vRet;
for (int i = k-1; i < m_c; i++)
{
vRet.emplace_back( max(vRight[i-k+1], vLeft[i]));
}
return vRet;
}
int m_c;
};

扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快
速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关
下载
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
| 我想对大家说的话 |
|---|
| 闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
| 如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用C++ 实现。

相关文章:
【二叉树】【单调双向队列】LeetCode239:滑动窗口最大值
作者推荐 map|动态规划|单调栈|LeetCode975:奇偶跳 涉及知识点 单调双向队列 二叉树 题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动…...
如何使用树莓派Bookworm系统中配置网络的新方法NetworkManager
树莓派在 10 月新出的 Bookworm 版本系统中,将使用多年的 dhcpcd 换成了 NetworkManager(以前是在rasp-config中可选),这是因为 Raspberry Pi OS 使用的是 Debian 内核(和 Ubuntu 一样),所以树莓…...
恶意软件分析沙箱在网络安全策略中处于什么位置?
恶意软件分析沙箱提供了一种全面的恶意软件分析方法,包括静态和动态技术。这种全面的评估可以更全面地了解恶意软件的功能和潜在影响。然而,许多组织在确定在其安全基础设施中实施沙箱的最有效方法方面面临挑战。让我们看一下可以有效利用沙盒解决方案的…...
ARM学习(24)Can的高阶认识和错误处理
笔者来聊一下CAN协议帧的认识和错误处理。 1、CAN协议帧认识 CAN 差分信号,是经过CAN收发器转成差分信号的,CAN RX和TX是逻辑电平。CAN的基础知识,可参考笔者这边文章:ARM学习(21)STM32 外设Can的认识与驱…...
网络通信--深入理解网络和TCP / IP协议
计算机网络体系结构 TCP/IP协议族 TCP / IP 网络传输中的数据术语 网络通信中的地址和端口 window端查看IP地址和MAC地址:ipconfig -all MAC层地址是在数据链路层的;IP工作在网络层的 MAC是48个字节,IP是32个字节 在子网(局域…...
IPC之九:使用UNIX Domain Socket进行进程间通信的实例
socket 编程是一种用于网络通信的编程方式,在 socket 的协议族中除了常用的 AF_INET、AF_RAW、AF_NETLINK等以外,还有一个专门用于 IPC 的协议族 AF_UNIX,IPC 是 Linux 编程中一个重要的概念,常用的 IPC 方式有管道、消息队列、共…...
学习在UE中通过Omniverse实现对USD文件的Live-Sync(实时同步编辑)
目标 前一篇 学习了Omniverse的一些基础概念。本篇在了解这些概念的基础上,我想体验下Omniverse的一些具体的能力,特别是 Live-Sync (实时同步) 相关的能力。 本篇实践了使用Omniverse的力量在UE中建立USD文件的 Live-Sync 编辑。由于相关的知识我是从…...
实现打印一个数字金字塔。例如:输入5,图形如下图所示
1*12**123***1234**** 12345*****#include<stdio.h> void main() {int i,j,l,n,k;scanf("%d",&n);/**********Program**********//********** End **********/ } 当我们拿到这个题目的时候可以看见题目给了我们五个变量,其中n是我们输入的数…...
hive sql常用函数
目录 一、数据类型 二、基础运算 三、字符串函数 1、字符串长度函数: length() 2、字符串反转函数:reverse 3、字符串连接函数 4、字符串截取函数 5、字符串分割函数:split 6、字符串查找函数 7、ascii 8、base64 9、character_length 10、c…...
Spark系列之:使用spark合并hive数据库多个分区的数据到一个分区中
Spark系列之:使用spark合并hive数据库多个分区的数据到一个分区中 把两个分区的数据合并到同一个分区下把其中一个分区的数据通过append方式添加到另一个分区即可 %spark val df spark.sql("select * from optics_prod.product_1h_a where datetime202311142…...
《重构-改善既有代
重要列表 1、如果你发现自己需要为程序添加一个特性,而代码结构使你无法很方便地达成目的,那就先重构哪个程序,使特性的添加比较容易的进行,然后再添加特性 2、重构前,先检查自己是否有一套可靠的测试机制࿰…...
vue3(七)-基础入门之事件总线与动态组件
一、事件总线 事件总线使用场景: 两个兄弟组件之间的传参,或者两个没有关联的组件之间的传参 html :引入 publicmsg 与 acceptmsg 自定义组件 (自定义组件名称必须小写) <body><div id"app"><publicmsg></…...
【计算机网络】网络层——IP协议
目录 一. 基本概念 二. 协议报文格式 三. 网段划分 1. 第一次划分 2. CIDR方案 3. 特殊的IP地址 四. IP地址不足 1. 私有IP和公网IP 2. DHCP协议 3. 路由器 4. NAT技术 内网穿透(NAT穿透) 五. 路由转发 路由表生成算法 结束语 一. 基本概念 IP指网络互连协议…...
《钢结构设计标准》中抗震性能化设计的概念
文章目录 0. 背景1. 前言2. 什么是抗震性能化设计3. 我国规范是如何实现性能化设计的4. 从能量角度理解性能化设计05. 《钢结构设计标准》抗震性能化设计的思路06. 《钢结构设计标准》抗震性能化设计的步骤 0. 背景 关于抗震性能化设计,之前一直理解的很模糊&#…...
【算法】【动规】回文串系列问题
文章目录 跳转汇总链接3.1 回文子串3.2 最长回文子串3.3 分割回文串 IV3.4 分割回文串II(hard) 跳转汇总链接 👉🔗动态规划算法汇总链接 3.1 回文子串 🔗题目链接 给定一个字符串 s ,请计算这个字符串中有多少个回文子字符串。 …...
4-Docker命令之docker logs
1.docker logs介绍 docker logs命令是用来获取docker容器的日志 2.docker logs用法 docker logs [参数] CONTAINER [root@centos79 ~]# docker logs --helpUsage: docker logs [OPTIONS] CONTAINERFetch the logs of a containerAliases:docker container logs, docker lo…...
svelte基础语法学习
官网文档地址:绑定 / Each 块绑定 • Svelte 教程 | Svelte 中文网 1、样式 一般情况下父子组件内样式隔离、同级组件间样式隔离 2、页面布局 <style>P{color: red;} </stye><script> // 类似data let name ‘jiang’ let countVal 0 let s…...
Node.js教程-mysql模块
概述 在Node.js中,mysql模块是实现MySQL协议的JavaScript客户端工具。Node.js程序通过与MySQL建立链接,然后可对数据进行增、删、改、查等操作。 安装 由于mysql模块不是Node.js内置模块,需手动安装 npm i mysql注意:若MySQL服…...
网络通信协议
WebSocket通信 WebSocket是一种基于TCP的网络通信协议,提供了浏览器和服务器之间的全双工通信(full-duplex)能力。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接ÿ…...
Spark集群部署与架构
在大数据时代,处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具,可以在集群中高效运行,处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群,以满足大规模数据处理的需求。 Spark集群架构…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
