[Leetcode]双项队列解决滑动窗口最大值难题
这道题是从优先队列的难题里面找到的一个题目。可是解法并不是优先队列,而是双项队列deque
其实只要知道思路,这一道题直接写没有太大的问题。我们看看题
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
示例:
输入: 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
翻译一下就是: 滑动区间里面每K个最大值
当然暴力naive的解法就显而易见了,用O(n*k)可以解决,不细说。但还是手痒写个伪代码:
for(size_t i=0;i<nums.size();i++){
int maxValue=INT_MIN;
for(size_t j=i;j<i+k;j++){
maxValue=max(maxValue,nums[j]);
}
res.push_back(maxValue);
}
我想到的另一种方法是建立一个最大堆。
想法很简单:每次读入一个新的数字,就把不在区间范围内的数字移除堆里,然后堆的顶部就是此次循环的结果。
一个堆其实非常容易实现。我们甚至可以使用一个C++ STL中的priority_queue。难点就在于,如何把这个不在区间范围内的数字移除。
However
在这里我介绍一种更快更通用的方法,使用双项队列。这里为了效率和快捷使用了deque容器,也可以使用list容器。
我声明了一个变量deque<int>window,用于存储下标。这个变量有以下特点:
- 变量的最前端(也就是
window.front())是此次遍历的最大值的下标 - 当我们遇到新的数时,将新的数和双项队列的末尾(也就是
window.back())比较,如果末尾比新数小,则把末尾扔掉,直到该队列的末尾比新数大或者队列为空的时候才停止,做法有点像使用栈进行括号匹配。 - 双项队列中的所有值都要在窗口范围内
特点一只是方便我们获取每次窗口滑动一格之后的最大值,我们可以直接通过window.front()获得
通过特点二,可以保证队列里的元素是从头到尾降序的,由于队列里只有窗口内的数,所以他们其实就是窗口内第一大,第二大,第三大...的数。
特点三就是根据题意设置的。但我们实际上只用比较现在的下标和window.front()就可以了,想想为什么?
Answer: 因为只要窗口内第一大元素也就是这个window.front()在窗口内,那我们可以不用管第二大第三大元素在不在区间内了。因为答案一定是这个第一大元素。如果window.front()不在窗口内,则将其弹出,第二个大元素变成第一大元素,第三大元素变成第二大元素以此类推。
代码编写的过程还要时刻检查队列是否为空防止抛出异常。
根据上面这些信息我们就可以编写此题的代码了。
Solution
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k==0)return {};
vector<int>res;
deque<size_t>window;
/*Init K integers in the list*/
for (size_t i = 0; i < k; i++) {
while (!window.empty() && nums[i] > nums[window.back()]) {
window.pop_back();
}
window.push_back(i);
}
res.push_back(nums[window.front()]);
/*End of initialization*/
for (size_t i = k; i < nums.size(); i++) {
if (!window.empty() && window.front() <= i - k) {
window.pop_front();
}
while (!window.empty() && nums[i] > nums[window.back()]) {
window.pop_back();
}
window.push_back(i);
res.push_back(nums[window.front()]);
}
return res;
}
};
[Leetcode]双项队列解决滑动窗口最大值难题的更多相关文章
- 【Leetcode堆和双端队列】滑动窗口最大值(239)
题目 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示例: 输入 ...
- [LeetCode] 239. Sliding Window Maximum 滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- [leetcode]239. Sliding Window Maximum滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- Leetcode 239.滑动窗口最大值
滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: ...
- Java实现 LeetCode 239 滑动窗口最大值
239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...
- LeetCoded第239题题解--滑动窗口最大值
滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 进 ...
- [Swift]LeetCode239. 滑动窗口最大值 | Sliding Window Maximum
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- 算法进阶面试题02——BFPRT算法、找出最大/小的K个数、双向队列、生成窗口最大值数组、最大值减最小值小于或等于num的子数组数量、介绍单调栈结构(找出临近的最大数)
第二课主要介绍第一课余下的BFPRT算法和第二课部分内容 1.BFPRT算法详解与应用 找到第K小或者第K大的数. 普通做法:先通过堆排序然后取,是n*logn的代价. // O(N*logK) pu ...
- Q239 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: 输入: nums ...
随机推荐
- 深入理解Jvm 虚拟机
参考: 内存模型:https://blog.csdn.net/qq_34280276/article/details/52783096 类加载原理:https://nomico271.github.i ...
- oracle随机数(转)
1.从表中随机取记录SELECT * FROM (SELECT * FROM STUDENT ORDER BY DBMS_RANDOM.RANDOM) WHERE ROWNUM < 4--表示从 ...
- HDU 6304 Chiaki Sequence Revisited
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=6304 多校contest1 Problem Description Chiaki is int ...
- MySQL 5.7.9版本sql_mode=only_full_group_by
这会导致select中只能出现group by后面出现的表的字段. 其实如果使用其他表的字段,聚合函数对无法对应其他表的字段. 建议放在子查询里. 如果想打破这个规则,可以设置sql_mode变量,将 ...
- jQuery实现动态分割div—通过拖动分隔栏实现上下、左右动态改变左右、上下两个相邻div的大小
由jQuery实现上下.左右动态改变左右.上下两个div的大小,需要自己引入jquery1.8.0.min.js包 可用于页面布局. //============================ind ...
- Add custom field in Material Master
1.Add fields in the Append Structure of table MARA. 2.Configure SPRO IMG -> Logistics General -&g ...
- Legend 图例
1.添加图例 >>> import matplotlib.pyplot as plt >>> import numpy as np >>> x = ...
- zeromq学习记录(八)负载均衡 附ZMQ_ROUTER的流程分析
/************************************************************** 技术博客 http://www.cnblogs.com/itdef/ ...
- ABP框架系列之十二:(Audit-Logging-审计日志)
Introduction Wikipedia: "An audit trail (also called audit log) is a security-relevant chronolo ...
- s3 Docker的镜像和容器
Docker技术里最为基础的两大概念:镜像和容器.镜像的 获取方式:从registry拉取,从Dockerfile构建:容器的基本操作 1 Docker架构和底层技术简介 Docker Platfor ...