描述
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{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]}。
窗口大于数组长度或窗口长度为0的时候,返回空。
数据范围: 1 \le n \le 100001≤n≤10000,0 \le size \le 100000≤size≤10000,数组中每个元素的值满足 |val| \le 10000∣val∣≤10000
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
示例:
输入:[2,3,4,2,6,2,5,1],3
返回值:[4,4,6,6,6,5]
class Solution {
public:
vector<int> maxInWindows(vector<int>& num, int size) {
// write code here
// vector<int> result,first;
// int end_;
// int n=num.size()-size+1;
// if(num.empty()||size==0||num.size()<size)
// return {};
// for(int i=0;i<n;i++)
// {
// end_=i+size-1;
// for(int j=0;j<size;j++)
// {
// first.push_back(num[j+i]);
// }
// sort(first.begin(),first.end());
// int a=first[size-1];
// result.push_back(a);
// first.clear();
// }
// return result;
//双端队列
vector<int> res;
if(size<=num.size()&&size!=0)
{
deque<int> dp;
for(int i=0;i<size;i++)
{
//去掉比自己小的,最后会留下第一个是最大的
while(!dp.empty()&&num[dp.back()]<=num[i])
dp.pop_back();
dp.push_back(i);
}
//遍历后面的
for(int i=size;i<num.size();i++)
{
res.push_back(num[dp.front()]);
while(!dp.empty()&&dp.front()<(i-size+1))
{
dp.pop_front();//删除窗口前面的元素
}
while(!dp.empty()&&num[dp.back()]<=num[i])
dp.pop_back();//最后会循环遍历,前面比它小的全删了
dp.push_back(i);//遍历完了再把自己插入
}
res.push_back(num[dp.front()]);//最后一次结果插入
}
return res;
}
};
总结:掌握双端队列的头插尾插,头删尾删和取头元素和尾元素