day13 2.27 栈与队列第二天
239. 滑动窗口最大值
链接: 239. 滑动窗口最大值
思路:(单调队列)主要就是pop、push、getMaxvalue。队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队里里的元素数值是由大到小的。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。
class Solution {
private:
class MyQueue{//单调队列(单调递增或递减)
public:
deque<int> que;//使用deque来实现单调队列
//每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出
//同时pop之前判断队列当前是否为空
void pop(int value){
if(!que.empty() && value == que.front()){
que.pop_front();
}
}
//如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素
//这样就保持单调队列的数值从小到大了
void push(int value){
while (!que.empty() && value > que.back()){
que.pop_back();
}
que.push_back(value);
}
//查询当前队列里的最大值,直接返回队列前端也就是front就可以了
int front(){
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> result;
for(int i = 0; i < k; i++){//先将前K个元素放进队列
que.push(nums[i]);
}
result.push_back(que.front());//result记录前K个元素的最大值
for(int i = k;i < nums.size();i++){
que.pop(nums[i - k]);//滑动窗口移除最前面的元素
que.push(nums[i]);//滑动窗口加入最后面的元素
result.push_back(que.front());//记录对应的最大值
}
return result;
}
};
347.前 K 个高频元素
链接: 347.前 K 个高频元素
思路:(优先级队列)大顶堆还是小顶堆
class Solution {
public:
//小顶堆
class mycomparison{
public:
bool operator()(const pair<int , int>& lhs,const pair<int, int>& rhs){
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
//要统计元素出现频率
unordered_map<int, int> map;//map<nums[i],对应出现的次数>
for(int i = 0;i < nums.size();i++){
map[nums[i]]++;
}
//对频率排序
//定义一个小顶堆,大小为K
priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparison> pri_que;
//用固定大小为K的小顶堆,扫描所有频率的数值
for(unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++){
pri_que.push(*it);
if(pri_que.size() > k){//如果堆的大小大于K,则队列弹出,保证堆的大小一直为K
pri_que.pop();
}
}
//找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒叙来输出到数组
vector<int> result(k);
for(int i = k - 1;i >= 0;i--){
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};