题意: 给定长度为
n
n
n的序列,问这个序列中每个长度为
k
k
k的连续子序列中最大元素值。
数据范围:可以做到
1
≤
n
≤
1
0
6
1\leq n\leq 10^6
1≤n≤106。
题解:
经典单调队列滑动窗口问题。
为了方便起见,第
i
i
i个元素为右端点的长度为
k
k
k的窗口称为窗口
i
i
i。
考虑当前加入的元素对之后窗口的影响,所以枚举到窗口 i i i,必须将第 i i i个元素加入新的窗口。由于求的是区间极值,自然会想到维护一个具有单调性的数据结构。
维护一个单调递减的队列,队列尾为当前枚举到的第 i i i个元素,由此可以得到长度至多为 k k k的单调队列,队头即窗口 i i i的最大值。
当继续枚举第
i
+
1
i+1
i+1个元素时,先将窗口缩小至多为
k
k
k。
之后这个窗口的最大值最少是第
i
+
1
i+1
i+1个元素,它们对之后的窗口不再有作用,所以我们考虑将第
i
+
1
i+1
i+1个元素前不比它大的元素全部弹出队列,将第
i
+
1
i+1
i+1元素加入队列即可。
代码:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& a, int k) {
int n = a.size();
vector<int> q(n), ans;
int hh = 0, tt = -1;
for(int i = 0; i < n; ++i) {
while(hh <= tt && i - q[hh] + 1 > k) ++hh;
while(hh <= tt && a[q[tt]] <= a[i]) --tt;
q[++tt] = i;
if(i + 1 >= k) ans.push_back(a[q[hh]]);
}
return ans;
}
};