(1)问题
力扣——239. 滑动窗口最大值 - 力扣(LeetCode)
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7]
(2)思路
使用队列来存储窗口中的元素,随着窗口移动,队列元素也不断插入和移除。然后每次寻找队列的最大值。但这样的时间复杂度为O(n*k)。如何用线性的时间解决该问题,就需要使用到单调队列,将窗口的最大值维护在队列首。这样每次就能直接获取当前窗口的最大值了。 那么这个单调队列就需要自己定义其功能。主要是插入、移除和返回队列首元素三个功能。
插入:如果插入元素大于队列尾元素,就删除队尾元素。然后再插入。
移除:如果移除的元素等于当前队首元素,才移除,否则不进行移除。
返回:返回队首元素。
自定义单调队列类的代码实现
class MyQueue{
public:
deque<int> que;
void push(int value)
{
while(!que.empty()&&value>que.back())
{
que.pop_back();
}
que.push_back(value);
}
void pop(int value)
{
if(!que.empty()&&value==que.front())
{
que.pop_front();
}
}
int front()
{
return que.front();
}
};
(3)解题流程
1.首先实例化自定义队列和创建结果数组。
2.将前K个元素移入队列。
3.将队首元素插入结果数组。
4.遍历数组剩下的元素。不断插入和删除队列元素。并将队首元素存储到结果数组中。
5.返回结果数组。
代码实现:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
MyQueue myqueue;
for(int i=0;i<k;i++)
{
myqueue.push(nums[i]);
}
ans.push_back(myqueue.front());
for(int i=k;i<nums.size();i++)
{
myqueue.pop(nums[i-k]);
myqueue.push(nums[i]);
ans.push_back(myqueue.front());
}
return ans;
}
这道题是使用单调队列的经典题目,单调队列并不是固定的。不同的题有不同的写法。只需要保证队列是单调递增或递减的即可。