《代码随想录》第五章 栈与队列 239. 滑动窗口最大值
努力学习!
题目:力扣链接
-
给你一个整数数组
nums,有一个大小为k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k 个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
一、思想
这道题的核心思想是使用单调队列。
单调队列是一种特殊的队列,它能够维护队列中元素的单调性(单调递增或单调递减)。在这道题中,我们需要维护一个单调递减的队列,以确保队列的头部始终是当前窗口的最大值。
为什么使用单调队列?
- 滑动窗口的最大值问题需要高效地找到每个窗口中的最大值。如果直接遍历每个窗口,时间复杂度会很高(O(n*k))。
- 单调队列通过维护一个单调递减的队列,能够在 O(1) 时间内获取当前窗口的最大值,同时通过移除不必要的元素,保持队列的简洁性。
二、代码
class Solution
{
private:
/**
* 自定义队列类,用于维护滑动窗口中的最大值
*/
class myQueue
{
public:
deque<int> que; // 使用双端队列存储窗口中的元素
/**
* 弹出元素:只有当要弹出的元素等于队首元素时才真正弹出
* @param value 要弹出的元素值
*/
void pop(int value)
{
if (!que.empty() && value == que.front()) {
que.pop_front();
}
};
/**
* 压入元素:维护队列的单调递减性
* @param value 要压入的元素值
*/
void push(int value)
{
// 移除所有小于当前值的元素,保持队列单调递减
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value); // 将当前值加入队列
}
/**
* 获取当前窗口的最大值(即队首元素)
* @return 当前窗口的最大值
*/
int front() { return que.front(); }
};
public:
/**
* 滑动窗口最大值算法
* @param nums 输入数组
* @param k 滑动窗口的大小
* @return 所有窗口的最大值
*/
vector<int> maxSlidingWindow(vector<int> &nums, int k)
{
myQueue que; // 创建自定义队列
vector<int> res; // 存储结果
// 初始化第一个窗口
for (int i = 0; i < k; ++i) {
que.push(nums[i]); // 将前k个元素加入队列
}
res.push_back(que.front()); // 记录第一个窗口的最大值
// 滑动窗口
for (int i = k; i < nums.size(); ++i) {
que.pop(nums[i - k]); // 移除窗口最左边的元素
que.push(nums[i]); // 加入窗口最右边的元素
res.push_back(que.front()); // 记录当前窗口的最大值
}
return res; // 返回所有窗口的最大值
}
};
三、代码解析
1. 算法工作原理分解
-
步骤 1:初始化单调队列:
- 创建一个单调递减队列
myQueue,用于存储当前窗口中的元素。 - 使用
deque<int> 实现队列,因为双端队列支持在头部和尾部的高效操作。
- 创建一个单调递减队列
-
步骤 2:初始化第一个窗口:
- 将前
k 个元素加入单调队列,并记录第一个窗口的最大值。
- 将前
-
步骤 3:滑动窗口:
-
对于每个新窗口,执行以下操作:
- 移除窗口左边界元素:如果窗口左边界元素等于队列头部元素,则移除队列头部元素。
- 加入窗口右边界元素:将新元素加入队列,并移除所有比它小的元素,保持队列的单调递减性。
- 记录当前窗口的最大值:队列头部元素即为当前窗口的最大值。
-
-
步骤 4:返回结果:
- 将所有窗口的最大值存储在结果数组
res 中,并返回。
- 将所有窗口的最大值存储在结果数组
2. 关键点说明
-
单调队列的维护:
- 单调队列的核心在于保持队列的单调递减性。每次加入新元素时,移除所有比它小的元素,确保队列头部始终是当前窗口的最大值。
-
窗口滑动的处理:
- 窗口滑动时,需要判断窗口左边界元素是否等于队列头部元素。如果相等,则移除队列头部元素,因为该元素已经不在当前窗口中。
-
时间复杂度优化:
- 通过单调队列的设计,每个元素最多被加入和移除队列一次,因此总体时间复杂度为 O(n)。
-
空间复杂度优化:
- 单调队列最多存储
k 个元素,因此空间复杂度为 O(k)。
- 单调队列最多存储
四、复杂度分析
-
时间复杂度:O(n)
- 每个元素最多被加入和移除队列一次,因此总体时间复杂度为 O(n)。
-
空间复杂度:O(k)
- 单调队列最多存储
k 个元素,因此空间复杂度为 O(k)。
- 单调队列最多存储
白展堂:人生就是这样,苦和累你总得选一样吧?哪有什么好事都让你一个人占了呢。 ——《武林外传》
1246

被折叠的 条评论
为什么被折叠?



