单调队列
经典类型:找出滑动窗口中的最大值/最小值
如果采用数组模拟队列
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++) {
while (hh <= tt && check_out(q[hh])) hh ++ ; // 判断队头是否滑出窗口
while (hh <= tt && check(q[tt], i)) tt -- ;
q[ ++ tt] = i;
}
直接采用STL的std::deque()
for (int i = 0; i < nums.size(); i++) {
if (!q.empty() && i - q.front() + 1 > k) q.pop_front();
while(!q.empty() && check(q.back(), i)) q.pop_back();
q.push_back(i);
}
练习题
在《剑指Offer专项突破版》中有两个练习题
239. 滑动窗口最大值利用单调队列可以做到时间复杂度为O(N),空间复杂度为O(K)
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> q;
vector<int> ans;
for (int i = 0; i < nums.size(); i++) {
if (!q.empty() && i - q.front() + 1 > k) q.pop_front();
while(!q.empty() && nums[q.back()] <= nums[i]) q.pop_back();
q.push_back(i);
if (i >= k-1) ans.push_back(nums[q.front()]);
}
return ans;
}
剑指 Offer59-II.队列的最大值也可以用单调队列来实现
class MaxQueue {
public:
MaxQueue() {}
int max_value() {
if (nums.empty()) return -1;
return maxQ.front();
}
void push_back(int value) {
nums.push(value);
while(!maxQ.empty() && maxQ.back() <= nums.back()) maxQ.pop_back();
maxQ.push_back(nums.back());
}
int pop_front() {
if (nums.empty()) return -1;
int ans = nums.front();
if (!maxQ.empty() && maxQ.front() == ans) maxQ.pop_front();
nums.pop();
return ans;
}
private:
deque<int> maxQ;
queue<int> nums;
};
练习题
参考资料
- 《剑指Offer专项突破版》