239. 滑动窗口最大值
初见想法:直接暴力搜索,但是其时间复杂度为O(n*k), 这题的精髓在于使用线性时间完成
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
myQueue que;
vector<int> ans;
for (int i = 0; i < k; i++)
{
que.push(nums[i]);
}
ans.push_back(que.max());
for (int i = k; i < nums.size(); i++)
{
que.pop(nums[i-k]);
que.push(nums[i]);
ans.push_back(que.max());
}
return ans;
}
// 实现一个单调队列, 这个单调队列的目的在于
// 其始终是单调递增的,队列的最前端即为最大值
class myQueue {
public:
deque<int> que; // 使用dequeue实现单调队列
void push(int val)
{
// 不断删除队列中小于val的数据
// 如果val是最大值,那可以把整个数据都删除
while (!que.empty() && val > que.back())
{
que.pop_back();
}
que.push_back(val);
}
void pop(int val)
{
// 滑动窗口在滑动时,会pop最左边的值, 判断是否是最大值
// 如果是最大值,则pop_front(), 维护最大值
if (!que.empty() && val == que.front())
{
que.pop_front();
}
}
int max()
{
return que.front();
}
};
};
实现单调队列,使用deque,维护一个单调递减的队列,deque的front就是最大值
在push的时候可以删除那些小于最大值的数据,在pop的时候判断是否为最大值,如果不是最大值可以直接不pop
整个解题思路就是滑动窗口,每往右滑动一次,先pop一个数据,再push一个数据
347.前 K 个高频元素
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> dic;
for (int i = 0; i < nums.size(); i++)
{
dic[nums[i]]++;
}
// 小顶堆
struct myComp {
bool operator()(pair<int, int> A, pair<int, int> B){
return A.second > B.second;
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, myComp> priority_que;
for (unordered_map<int, int>::iterator it = dic.begin(); it != dic.end(); it++)
{
priority_que.push(*it);
if (priority_que.size() > k)
{
priority_que.pop();
}
}
vector<int> ans;
while (!priority_que.empty())
{
ans.push_back(priority_que.top().first);
priority_que.pop();
}
return ans;
}
// 小顶堆
struct myComp {
bool operator()(pair<int, int> A, pair<int, int> B){
return A.second > B.second;
}
};
};
使用小顶堆构建优先队列
注意构建小顶堆的构建方法