题目描述
知识点
单调队列
我的实现
结果
码前思考
这道题我没有想出来,我是看了大佬的题解才会做的。。。
代码实现
//使用单调队列来解题
//需要理解单调队列的思想
class Solution {
public:
deque<int> data;
void push(int n){
while(!data.empty() && data.back() < n){
data.pop_back();
}
data.push_back(n);
}
int getMax(){
return data.front();
}
void pop(int n){
if(!data.empty()&&data.front()==n){
data.pop_front();
}
}
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
for(int i=0;i<nums.size();i++){
if(i<k-1){
push(nums[i]);
}else{
//说明要开始往右边移动了
//首先尝试弹出左边那个元素
push(nums[i]);
res.push_back(data.front());
pop(nums[i-k+1]);
}
}
return res;
}
};
码后反思
关于这道题目中的单调队列我的理解:
摘取下面这段代码分析:
//说明要开始往右边移动了
//首先尝试弹出左边那个元素
push(nums[i]);
res.push_back(data.front());
pop(nums[i-k+1]);
首先看这行代码:
push(nums[i]);
这行代码的意思是尝试将i
放入到一个大小小于等于k-1
的data
的末尾。我们知道在push()
的过程中,我们会将data
中值比nums[i]
小的元素弹出来,并且保持data
的单调性。那么完成push()
操作之后,此时data
中存放的就是i-k+1~i
这个窗口中,值大于等于num[i]
的值。
接下来是这段代码:
res.push_back(data.front());
没什么好讲,就是得到最大值。
最后是这段代码:
pop(nums[i-k+1]);
这个操作相当于将左边界向右移动一步。
这是这个解法的点睛之笔。
我们将其与data.front()
做比较,如果它不是data.front()
,也是就是窗口i-k+1~i
的最大值,那么它肯定小于这个data.front()
,那么我们可以确定的是data.front()
这个元素入队或者之前,这个nums[i-k+1]
就被出队了。
其实这个解法的出发点在于如何优化暴力解法。