【二叉树】【单调双向队列】LeetCode239:滑动窗口最大值

本文主要是介绍【二叉树】【单调双向队列】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:滑动窗口最大值的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/534906

相关文章

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi

bat脚本启动git bash窗口,并执行命令方式

《bat脚本启动gitbash窗口,并执行命令方式》本文介绍了如何在Windows服务器上使用cmd启动jar包时出现乱码的问题,并提供了解决方法——使用GitBash窗口启动并设置编码,通过编写s... 目录一、简介二、使用说明2.1 start.BAT脚本2.2 参数说明2.3 效果总结一、简介某些情

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s