leetcode239:滑动窗口最大值
文章讲解:leetcode239
leetcode347:前k个高频元素
文章讲解:leetcode347
目录
1,leetcode239 滑动窗口最大值:
第一眼看到以为是优先队列,但是发现窗口是挪动的,优先队列每次只能取出最大的,没思路了。
看了题解之后理解了,这道题核心是设计这个单调队列。单调队列中每次移动维护最大的值即可:
class Solution {
private:
class MyQueue {
public:
deque<int> que;
void pop(int value) {
if (!que.empty() && value == que.front()) {
que.pop_front();
}
}
void push(int value) {
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value);
}
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++) {
que.push(nums[i]);
}
result.push_back(que.front());
for (int i = k; i < nums.size(); i++) {
que.pop(nums[i - k]);
que.push(nums[i]);
result.push_back(que.front());
}
return result;
}
};
核心就是这个队列中的pop和push方法,思路就是让队首的元素是最大的。在放入的时候,前面的小元素都要弹出器。这样处理的话,就只需要在弹出的是最大值时再弹出即可,如果弹出的不是窗口中的最大值,那在之前或者之后的处理都会被弹出。
2,leetcode347 前k个高频元素
这道题就很显然是个优先队列问题了,只需要先统计一下各个元素出现的频率,放到优先队列排列即可,唯一需要注意的就是传一个比较函数进去:
class Solution {
public:
static bool cmp(pair<int, int>& a, pair<int, int>& b) {
return a.second > b.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> omap;
for (auto& v : nums) {
omap[v]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
for (auto& [num, count] : omap) {
if (q.size() == k) {
if (q.top().second < count) {
q.pop();
q.emplace(num, count);
}
} else {
q.emplace(num, count);
}
}
vector<int> result;
while (!q.empty()) {
result.emplace_back(q.top().first);
q.pop();
}
return result;
}
};
和随想录思路是一致的。
3,总结
我感觉栈和队列由于他们性质特殊,操作有局限,因此整体上比链表要容易理解一些。难点是在题目中识别出使用这两个数据结构。