题目描述:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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 | 2 | 2 | 2 | |
1 | 3 | 2、3 | 3 | |
2 | 4 | 2、3、4 | 4(大于3) | 4 |
3 | 2 | 3、4、2 | 4、2(小于4) | 4 |
4 | 6 | 4、2、6 | 6(大于4、2) | 6 |
5 | 2 | 2、6、2 | 6、2(小于6) | 6 |
6 | 5 | 6、2、5 | 6、5(大于2) | 6 |
7 | 1 | 2、5、1 | 5、1(删除6,因为已经不在窗口中) | 5 |
代码:
class solution
{
public:
vector<int> MaxNums(vector<int> data,int size)
{
deque<int> dataIndex;
vector<int> result;
/*先输入开头size个数据*/
for(int i=0;i<size;i++)
{
while(!dataIndex.empty()&&data[i]>=data[dataIndex.back()])
{
dataIndex.pop_back();
}
dataIndex.push_back(data[i]);
}
result.push_back(data[dataIndex.front()]);
/*从第size个数据开始往后遍历*/
for(int i=size;i<data.length();i++)
{
/*当遍历到的数据比双端队列尾的数据大于等于时,抛掉双端队列尾端数据,直到双端队列开头数据是最大值*/
while(!dataIndex.empty()&&data[i]>=data[dataIndex.back()])
{
dataIndex.pop_back();
}
/*当前的索引与双端队列开头数据索引之差大于等于size时,说明队列开头数据已经不在窗口中*/
if((i-dataIndex.front)>=size)
{
dataIndex.pop_front();
}
dataIndex.push_back(i);
result.push_back(data[dataIndex.front()]);
}
return result;
}
}
代码2:
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
int len = num.size();
vector<int> result;
if(len < size||size==0)
return result;
for(int i=0; i<=len-size; i++)
{
int max = num[i];
for(int j = i; j< i+size;j++)
{
if(num[j]>max)
max = num[j];
}
result.push_back(max);
}
return result;
}
};