主页有其他数据结构内容(持续更新中)
难度:Hard
代码:
Solution1:比较容易想到优先队列(效率较低)
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
priority_queue<pair<int, int>> pq;
vector<int> res;
for(int i = 0; i < k; i++){ // 把前k个放入优先队列
pair<int, int> temp(nums[i], i);
pq.push(temp);
}
res.emplace_back(pq.top().first); // 根据优先队列默认的降序排列,把队头插入结果数组
for(int j = k; j < nums.size(); j++){
pair<int, int> temp(nums[j], j);
pq.push(temp);
while(!pq.empty() && pq.top().second <= j - k){
// 这里要用while,不能用if,很关键!
// 必须把所有不符合条件的队头全部出队
pq.pop();
}
res.emplace_back(pq.top().first);
}
return res;
}
};
Solution2:利用双端队列(推荐!),实际上是单调栈的一个延伸,确保队列内部(对应原数组中的值)是降序排列,因此可以轻松获取每个窗口内的最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
deque<int> window;
// 把前k个初始化
for (size_t i = 0; i < k; i++) {
while (!window.empty() && nums[i] > nums[window.back()]) {
// 当前元素比队尾大,就把队尾弹出
// 确保双端队列(nums的索引对应的值)是降序
window.pop_back();
}
window.push_back(i); // 当前元素入队
}
res.push_back(nums[window.front()]); // 队头元素对应的nums的值是当前窗口最大
for (size_t i = k; i < nums.size(); i++) {
if (!window.empty() && window.front() <= i - k) {
// 只要窗口内最大元素window.front()在窗口内,那就可以不用管第二大、第三大元素在不在区间内了
// 如果 window.front() 不在窗口内,则将其弹出
window.pop_front();
}
while (!window.empty() && nums[i] > nums[window.back()]) {
window.pop_back();
}
window.push_back(i);
res.push_back(nums[window.front()]);
}
return res;
}
};