单调队列
题目来自leetcode 239题滑动窗口最大值
如果使用暴力做法的话,每一次的窗口中都遍历找最大,这样的算法时间复杂度是O(n2),显然不符合要求!
这题应该使用单调队列来解决,时间复杂度为O(n)。
单调队列就是队列中的数据要么是单调递增,要么是单调递减的。
这里我们借助STL中的双端队列可以很好的实现单调队列。
代码如下
1 class Solution { 2 public: 3 vector<int> maxSlidingWindow(vector<int>& a, int k) { 4 vector<int> ans; 5 if (k == 0) 6 return a; 7 deque<int> deq; 8 for (int i = 0; i < a.size(); i++) 9 { 10 while (!deq.empty() && deq.back() < a[i]) deq.pop_back(); 11 if (!deq.empty() && i >= k && a[i - k] == deq.front()) deq.pop_front(); 12 deq.push_back(a[i]); 13 if (i >= k - 1) 14 ans.push_back(deq.front()); 15 } 16 return ans; 17 } 18 };
while (!deq.empty() && deq.back() < a[i]) deq.pop_back();
每一个元素在入队的时候都要从队尾开始判断队列中的元素是否小于自己,如果小于的话就将其踢出队列,保证队列的单调性。
if (!deq.empty() && i >= k && a[i - k] == deq.front()) deq.pop_front();
i>=k保证在前k个数据不会触发if条件,前k个元素之后,窗口开始移动,窗口最左边的元素会被移出,这个时候被移除的元素可能是最大值也可能不是。这个时候我们就要判断 a[i - k] == deq.front(),因为如果被移除的元素是最大值的话,那么它一定在队首,此时我们将对手元素出队就好了,而如果被移除的元素不是之前窗口中的最大值的话,我们就不用管它,因为那个元素早就被移出了队列了。