滑动窗口最大值
题目描述:给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
思路
1.暴力求解,超时!
2.实现一个单调队列,自己 diy 一种队列,与优先级队列不同,我们自己实现的单调队列的pop和push可以自定义。
实际上,只需要维护 可能 是最大值的数据。
基于双端队列 deque 来维护这个单调队列
单调队列
pop操作:也就是移除左端元素,想想什么时候pop。
举个例子:nums = [1,3,-1,-3,5,3,6,7], k = 3
当5准备入队时,最左端的3要被移除,因为元素3的下标是1,而元素5的下标是4,相差3,也就是k
push操作:队列中存的是下标,下标对应的值是从大到小排列的,每当要push一个元素时,从后往前删除不大于该元素的所有元素
getMaxValue操作:即队头元素
代码
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> result;
deque<int> dq; // 起到单调队列的作用 下标不单调,但对应的值单调 大 -> 小
// 保存可能成为最大值的元素
// 存下标,而不是存值 原因:存下标可以帮助判断该元素什么时候被移出去
int n = nums.size();
for (int i = 0; i < n; i++)
{
// pop操作
// 当队列非空且队头元素下标与当前要push进去的元素下标相差k时,pop
if (dq.empty() != 1 && (i - dq.front() == k))
dq.pop_front(); // 左端最大值不能再用
// push操作
// 队列非空时,删除队列中不大于nums[i]的元素
while (dq.empty() != 1 && nums[dq.back()] <= nums[i])
dq.pop_back();
dq.push_back(i);
// getMaxValue操作
if (i > k - 2)
result.push_back(nums[dq.front()]);
}
return result;
}
};