使用单调队列解决滑动窗口的最大值
#include <iostream>
#include <deque>
#include <vector>
using namespace std;
class MonotonicQueue { // 构建单调队列
private:
deque<int> data;
public:
void push(int n) {
while (!data.empty() && data.back() < n) {
data.pop_back();
}
data.push_back(n);
}
int max() {
return data.front();
}
void pop(int n) {
if (!data.empty() && data.front() == n) {
data.pop_front();
}
}
};
class Solution {
public:
// 使用单调队列
vector<int> maxWindowSlide(vector<int>& nums, int k) {
vector<int> res;
MonotonicQueue window;
for (int i = 0; i < nums.size(); i++) {
if (i < k - 1) {
window.push(nums[i]);
}
else {
window.push(nums[i]);
res.push_back(window.max());
window.pop(nums[i-k+1]);
}
}
return res;
}
/*
遍历数组,将数存放在双向队列中,并用L,R来标记窗口的左边界和右边界。队列中保存的并不是真的数,
而是该数值对应的数组下标位置,并且数组中的数要从大到小排序。如果当前遍历的数比队尾的值大,则需要弹出队尾值,
直到队列重新满足从大到小的要求。刚开始遍历时,L和R都为0,有一个形成窗口的过程,此过程没有最大值,L不动,R向右移。
当窗口大小形成时,L和R一起向右移,每次移动时,
判断队首的值的数组下标是否在[L,R]中,如果不在则需要弹出队首的值,当前窗口的最大值即为队首的数。
*/
// 使用双端队列
vector<int> maxWindowSlide2(vector<int>& nums, int k) {
vector<int> res;
deque<int> dq;
int i = 0;
int j = 0;
while(i< nums.size()) {
while (j < nums.size()) {
while (!dq.empty() && nums[dq.back()] < nums[j]) {
dq.pop_back();
}
dq.push_back(j);
j++;
}
if (dq.front() <= i-k) { // 判断当前队列中队首的值是否有效(过期)
dq.pop_front();
}
if (i >= k-1) { // 当窗口长度为k时 保存当前窗口中最大值
res.push_back(nums[dq.front()]);
}
i++;
}
return res;
}
};
这里在记录一个别人的答案(双端队列解决),简短不失优雅。
class Solution2 {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> res;
deque<int> s;
for (unsigned int i = 0; i < num.size(); ++i) {
while (s.size() && num[s.back()] <= num[i])//从后面依次弹出队列中比当前num值小的元素,同时也能保证队列首元素为当前窗口最大值下标
s.pop_back();
while (s.size() && i - s.front() + 1 > size)//当当前窗口移出队首元素所在的位置,即队首元素坐标对应的num不在窗口中,需要弹出
s.pop_front();
s.push_back(i);//把每次滑动的num下标加入队列
if (size && i + 1 >= size)//当滑动窗口首地址i大于等于size时才开始写入窗口最大值
res.push_back(num[s.front()]);
}
return res;
}
};
void main() {
Solution S;
vector<int> nums{ 9,7,10,5,8,3,6 };
int k = 3;
//vector<int> res = S.maxWindowSlide(nums, k);
//for (auto s : res) {
// cout << s;
//}
//cout << endl;
vector<int> res2 = S.maxWindowSlide2(nums, k);
for (auto n : res2) {
cout << n;
}
}