题目描述
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
解题思路
利用优先级队列来进行求解
创建一个pair<int,int>p来存储输入向量中每个元素的值和索引。
创建一个优先级队列“q”,根据它们的值按降序存储对“p”。
首先遍历输入向量中的前k个元素,并将每对 “p” 添加到优先级队列 “q” 中。
通过检索优先级队列“q”中具有最大值的顶部元素的值,获得第一个子数组的最大值。
然后开始滑动窗口:
通过一次向右滑动窗口一个元素来遍历输入向量中的剩余元素。
从索引小于或等于当前子数组的左边界的优先级队列“q”中删除所有对“p”。这样可以确保优先级队列中的最大值始终在当前子数组(窗口)中。
将当前元素添加到优先级队列“q”中。 通过检索优先级队列“q”中顶部元素的值,获得当前子数组的最大值。
滑动窗口,直到到达输入数组的末尾。
总之,该函数使用优先级队列来有效地找到输入向量中长度为k的每个滑动窗口中的最大值。
AC代码如下:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int>ans;
pair<int, int>p;
priority_queue<pair<int, int>>q;
for(int i = 0; i < k; i++) q.push(make_pair(nums[i], i));
ans.push_back(q.top().first);
int left = 0, right = k;
while(right < nums.size()) {
while(!q.empty() && q.top().second <= left) q.pop();
q.push(make_pair(nums[right], right));
left++, right++;
ans.push_back(q.top().first);
}
return ans;
}
};
扩展一下,找滑动窗口最小值
有了上述思路,寻找滑动窗口最小值便变得非常简单,我们可以通过自定义优先级队列的的优先级即可,也就是说值越小优先级越高。
可以通过重载运算符 “<” 来自定义priority_queue的优先级。具体来说,如果我们想要在队列中按照第一个元素的大小升序定义优先级,则可以这样实现:
struct cmp {
bool operator() (const pair<int, int>& a, const pair<int, int>& b) {
return a.first > b.first;
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q;
通过重载运算符 “<” 来自定义priority_queue的优先级。其中,结构体cmp重载了小于号运算符,使得在队列中按照pair的第一个元素的大小定义优先级,第一个元素越小优先级越高。注意,这里的第二个参数是一个vector,表示底层容器的类型,第三个参数是一个比较器,表示优先级的比较方式。
在优先级队列中,自定义排序cmp的作用看上去似乎和sort中的自定义排序相反了。其原因在于优先级队列本身默认的规则就是优先级高的放在队首,因此把小于号重载为大于号的功能时只是把这个规则方向了一下。因此要记住优先队列的这个函数与sort中的cmp函数的效果是相反的。
全部代码如下:
class Solution {
public:
struct cmp {
bool operator() (const pair<int, int>& a, const pair<int, int>& b) {
return a.first > b.first;
}
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int>ans;
pair<int, int>p;
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp>q;
for(int i = 0; i < k; i++) q.push(make_pair(nums[i], i));
ans.push_back(q.top().first);
int left = 0, right = k;
while(right < nums.size()) {
while(!q.empty() && q.top().second <= left) q.pop();
q.push(make_pair(nums[right], right));
left++, right++;
ans.push_back(q.top().first);
}
return ans;
}
};