1、思路
初见这个题可能会想到用两个指针来代表窗口的前后边界,但这样实现代码会非常复杂。最好的方式应该是用一个双端队列deque
来构造单调栈,队列中存放的是元素下标,队头为窗口内最大元素的下标,当队头元素(下标)已经超出窗口范围时,我们把这个元素叫作过期元素,需要弹出。主要的四个步骤如下:
- 队列不为空且队头元素已过期,则弹出队头元素;
- 队列不为空且队尾元素 ≤ 当前元素,则弹出所有小于等于当前元素的队尾元素;
- 插入当前元素;
- 窗口已经完全进入数组中,将窗口中的最大值插入结果数组。
2、代码
#include <iostream> #include <vector> #include <deque> using namespace std; int main() { int n, windowSize; cin >> n >> windowSize; vector<int> nums, res; deque<int> q; for (int i = 0; i < n; ++ i) { int tmp; cin >> tmp; nums.push_back(tmp); } for (int i = 0; i < n; ++ i) { if (q.size() && q.front() <= i - windowSize) q.pop_front(); //1. while (q.size() && nums[q.back()] <= nums[i]) q.pop_back(); //2. q.push_back(i); //3. if (i >= windowSize - 1) res.push_back(nums[q.front()]); //4. } for (int i : res) { cout << i << " "; } return 0; }