单调队列
- 单纯的滑动窗口只能在滑动增加的时候比较新值和原来的最值。如果要删去尾部就不能用了,因为如果删除的恰好是最值,那就要吧原来的值全部遍历一遍了。
- 单纯的优先队列,不能满足【先进先出】的时间顺序
滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
链接:https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
1 用单调队列,维护一个从front到back单调递减的队列。每次状态改变的时候,考虑会不会破坏单调性,考虑最大值会不会被删除,如果删除了pop(),取第二个值,如果不删除就不管。也就是单调队列的大小和滑动窗口的大小是不一致的,只考虑单调性和求每个状态的极值。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//维护一个单调队列,保存此时大小的序列
int n_size = nums.size();
// 题目给出k总是有效的
if (!n_size) {
return {};
}
deque<int> dq1;
vector<int> ret;
for (int fast = 0, slow = 1 - k; fast < n_size; ++fast, ++slow){
// 删除slow-1 有影响的时候删除slow-1 有影响的意思是上一个slow-1是最大值front但是尾部slow-1需要被窗口删除
// 否则不删除,因为只要得到最大值,小的值不影响
if (!ret.empty() && dq1.front() == nums[slow-1]){
dq1.pop_front();
}
// 删除back,为了之后插入fast的时候能维护单调性
while (!dq1.empty() && dq1.back() < nums[fast]){
dq1.pop_back();
}
dq1.push_back(nums[fast]);
// 插入结果
if (slow >= 0){
ret.push_back(dq1.front());
}
}
return ret;
}
};
队列的最大值
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/dui-lie-de-zui-da-zhi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- 维护一个单调队列
class MaxQueue {
public:
MaxQueue() {
}
int max_value() {
return nums.empty() ? -1 : orderedq.front();
}
void push_back(int value) {
while (!orderedq.empty() && value > orderedq.back()){
orderedq.pop_back();
}
orderedq.push_back(value);
nums.push(value);
}
int pop_front() {
if (nums.empty()){
return -1;
}
int num = nums.front();
if (num == orderedq.front()){
orderedq.pop_front();
}
nums.pop();
return num;
}
private:
deque<int> orderedq;
queue<int> nums;
};
/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue* obj = new MaxQueue();
* int param_1 = obj->max_value();
* obj->push_back(value);
* int param_3 = obj->pop_front();
*/