给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
思路:这道题感觉很难理解,先看的剑指offer,那上面很好理解,但是给出的代码很不懂,看下面的版本,使用双端队列deque,对队列和双端队列非常不懂,
queue的首先从左到右压入元素,最先压入的元素在右侧,叫队头使用front进行访问,最后push的元素使用back进行访问。
deque首先压入的元素也是在队头,使用front访问,压入使用pop_front,队尾使用back访问,压入队尾是pop_back。
访问里面的元素只能访问端口,不能使用迭代器进行访问。
本题使用deque,结果存在数组里面,首先使用一个循环将队列中队首前面小于当前元素的都删除,队列里面存储的是元素下标,这样做的好处是可以很容易判断当前元素是否已经超出滑动窗口,这里是使用front,然后使用判断是否超出滑动窗口的尺寸,因为back元素是最先压入的,(pop_front压元素,back是最先压入的元素),所以if判断当前下标和back之间相差的个数是否大于滑动窗口*(首-尾+1),不管怎样,都需要将该元素压进去,然后判断,这里很难想到。最后因为前size元素是特殊情况,滑动窗口还没满,需要特殊处理。
class Solution { 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() > 0 && num[s.front()]<=num[i]) //如果队首元素小于当前元素,则弹出,不可能成为最大值 s.pop_front(); if(s.size() > 0 && i-s.back()+1>size) //back元素最先放进去的,所以和back的下标比较 s.pop_back(); s.push_front(i);//把每次滑动的num下标加入队列 if(size && i+1>=size)//当滑动窗口首地址i大于等于size时才开始写入窗口最大值 res.push_back(num[s.back()]); } return res; } };
原文地址:https://www.cnblogs.com/dingxiaoqiang/p/8452351.html