LeetCode 239 滑动窗口最大值
题目链接:https://leetcode.cn/problems/sliding-window-maximum/
思路:
建立一个单调队列来进行操作。单调队列的特点就是队列里面的数值排序是单调的。重点在于只要维护最大值或者是有可能成为最大值的值即可。保持最大值一直在队列的front,这样读取最大值时,只要读队列的front即可。
![](https://img-blog.csdnimg.cn/img_convert/491ee0aee796c21521b5d0e46ee22d21.gif)
代码:
单调队列的实现并不是固定的,需要根据题目要求来进行变化。关键点在于保持队列内元素是单调排序的。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int>result;
Myque que;
// 先将前k个数加入到单调队列中
for(int i = 0;i<k;i++)
{
que.push(nums[i]);
}
// 记录前k个数中的最大值
result.push_back(que.getMaxVale());
for(int i=k;i<nums.size();i++)
{
// 移除窗口最左边的数
que.pop(nums[i-k]);
// 加入窗口最右边的数
que.push(nums[i]);
result.push_back(que.getMaxVale());
}
return result;
}
private:
// 单调队列
class Myque {
public:
void pop(int val)
{
if(!que.empty()&&val == que.front())
que.pop_front();
}
void push(int val)
{
// 将入口处小于val的值pop掉
while(!que.empty()&&val > que.back())
que.pop_back();
que.push_back(val);
}
int getMaxVale()
{
return que.front();
}
private:
deque<int>que;
};
};
总结
第一次知道单调队列的思想,需要在后面多加学习。
LeetCode 347 前 K 个高频元素
题目链接:https://leetcode.cn/problems/top-k-frequent-elements/
思路:
先用哈希表(unordered_map)将元素出现的频率进行排序,其中key是元素,value是出现频率。然后定义一个小顶堆,将该小顶堆的大小固定为K,然后通过小顶堆对频率次数进行排序。注意,此时小顶堆从上到下,频率依次提高,因此用数组保存小顶堆的值时,要从后往前保存。
代码:
为什么使用小顶堆?
答:如果使用大顶堆,此时根节点是最大值,当大顶堆中的元素大于k个时,要进行pop操作,然而pop操作是对根节点进行操作,即将根节点pop出去。所以会将最大值pop出去。如果是小顶堆,则会是将最小值pop出去,满足题意要求。
大顶堆如何定义?
答:priority_queue<Type, Container, Functional>,只填Type的参数,出来的就会是大顶堆。
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;
for(int i = 0;i<nums.size();i++)
{
map[nums[i]]++;
}
// 对频率进行排序
// 定义一个小顶堆
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)
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;
}
};
总结:
想到了使用哈希表来保存元素的频率,而且想着如果要对哈希表的value进行排序时间会很长,对哈希表也不熟悉,所以没有写出实现方法,而是直接去看了题解。第一次看到大顶堆和小顶堆这两个数据结构。
今日总结:
收获满满,需要后面再次复习吸收。