更多精彩文章持续更新,微信搜索「代码随想录」第一时间围观,本文https://github.com/youngyangyang04/TechCPP 已经收录,里面有更多干货等着你,欢迎Star!
题目地址
https://leetcode-cn.com/problems/sliding-window-maximum/
思路
这是使用单调队列的经典题目。
暴力方法,遍历一遍的过程中每次从窗口中在找到最大的数值,这样很明显是O(n * k)的算法。
有的同学可能会想用一个大顶堆也就是优先级队列来存放这个窗口里的k个数字,这样就可以知道最大的最大值是多少了, 但是问题是这个窗口是移动的,而大顶堆每次只能弹出最大值,我们无法移除其他数值,这样就造成大顶堆维护的不是滑动窗口里面的数值了。所以不能用大顶堆。
使用单调队列,即单调递减或单调递增的队列。 它不是一个独立的数据结构,需要使用其他数据结构来实现单调队列,例如: deque,deque是双向队列,可以选择 从头部或者尾部pop,同样也可以从头部或者尾部push。
不要以为实现的单调队列就是 对窗口里面的数进行排序,如果排序的话,那和优先级队列又有什么区别了呢。
详情看代码吧,已经简洁。
C++代码
class Solution {
public:
class MyQueue { //单调队列(从大到小)
public:
deque<int> que; // 使用deque来实现单调队列
void pop(int value) {
if (!que.empty() && value == que.front()) {
que.pop_front();
}
}
void push(int value) {
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value);
}
int front() {
return que.front();
}
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> result;
for (int i = 0; i < k; i++) { // 先将前k的元素放进队列
que.push(nums[i]);
}
result.push_back(que.front()); // result 记录前k的元素的最大值
for (int i = k; i < nums.size(); i++) {
que.pop(nums[i - k]); // 模拟滑动窗口的移动
que.push(nums[i]); // 模拟滑动窗口的移动
result.push_back(que.front()); // 记录对应的最大值
}
return result;
}
};
更过算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。