239.滑动窗口最大值
思路:滑动窗口每移动一次,滑动窗口中去除第一个元素,后面加入一个元素,获得一次滑动窗口的最大值。因此我们自定义pop、push、getMaxvalue函数,将滑动窗口内的元素排列成单调队列。单调队列的头部一直是最大元素,当滑动窗口移动时,我们需要向单调队列中push元素,当我们push的元素比队列中的尾部元素大时,就把队列的尾部元素pop出去,然后再将元素push进去,因为我们只需要滑动窗口中最大的元素。当需要pop的元素和头部元素相同时,将头部元素pop出去,因为如果不相同说明此时需要pop的元素不是滑动窗口中最大的元素,在push的过程中就被pop出去了,然后在每次移动过程中,都取滑动窗口的头部,即最大值,遍历数组,收集到滑动窗口最大值的数组返回。
class Solution {
public:
//DIY pop函数
//DIY push函数
//DIY getMaxvalue函数
//DIY 单调队列
class MyQueqe
{
public:
deque<int> q1;
void pop(int val)
{
if(!q1.empty() && val==q1.front())
{
q1.pop_front();
}
}
void push(int val)
//从后往前删
{
while(!q1.empty()&&val>q1.back())
{
q1.pop_back();
}
q1.push_back(val);
}
int getMaxvalue()
{
return q1.front();
}
};
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueqe q1;
vector<int> result;
for(int i =0;i<k;i++)
{
q1.push(nums[i]);
}
result.push_back(q1.getMaxvalue());
for(int i =k;i<nums.size();i++)
{
q1.pop(nums[i-k]);
q1.push(nums[i]);
result.push_back(q1.getMaxvalue());
}
return result;
}
};
345.前K个高频元素
思路:利用map,获取整数数组中元素出现的频率。然后构造一个小顶堆,即堆的顶部一直是最小的元素,这样方便我们pop出去,在堆内部留下大的元素。最后构造一个k长度的数组,从后向前填充元素,填充的元素为小顶堆的头部。
class Solution {
public:
//小顶堆
class mycompare{
public:
bool operator()(pair<int,int>&p1,pair<int,int>&p2)
{
return p1.second>p2.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
priority_queue<pair<int,int>,vector<pair<int,int>>,mycompare> pri_que;
unordered_map<int,int> map;
for(int i =0;i<nums.size();i++)
{
map[nums[i]]++;
}
for(unordered_map<int,int>::iterator it=map.begin();it!=map.end();it++)
{
pri_que.push(*it);
if(pri_que.size()>k)
{
pri_que.pop();
}
}
vector<int> result(k);
for(int i=k-1;i>=0;i--)
{
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};
收获:
1、学会了使用单调队列,在寻找滑动窗口内部的最大值时,判断滑动窗口中比push的那个元素小的元素是没意义的,因此在push之前,先把比它小的元素pop出去(从后往前)。
2、学会了使用小顶堆,利用priority_queue构建优先队列,根据自己写的compare类,类内重载()的return来控制大顶堆和小顶堆,利用小顶堆,当堆的元素超出k时,移出栈顶元素,此时栈顶元素为最小的元素,因此最后留下的元素都是最大的元素。由于栈底的元素才是最大的元素,所以定义的数组从后往前填充,顺序就为从大到小了。