239. 滑动窗口最大值
困难级别的题,上来就乱了
思路:长度为k的区间移动,每次要扔掉最后一个,添加最前面一个;
以及最后一个是不是最大值,如果是,那新的最大值怎么找?
找最大值,用最后一个是不是最大值来判断,给自己埋了坑,这样不一定好做。
用大顶堆应该很容易,哦也不容易,最左边的元素非最大值,那就不好弹出了;
这版官方题解也是我一开始的思路,这里没有每次都弹出左边界的值,而是判断堆顶是否在界内,完成筛选,思路也挺好的。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
priority_queue<pair<int, int>> q;
for (int i = 0; i < k; ++i) {
q.emplace(nums[i], i);
}
vector<int> ans = {q.top().first};
for (int i = k; i < n; ++i) {
q.emplace(nums[i], i);
while (q.top().second <= i - k) {
q.pop();
}
ans.push_back(q.top().first);
}
return ans;
}
};
联想其他题目:取前k个最大值
Ques:啊,并没有学明白,什么时候用在类里用构造函数,什么时候直接定义一个容器。
class Solution {
private:
class MyQueue{
public:
deque<int> que;
void push(int x) {
while (!que.empty() && x > que.back())
que.pop_back();
que.push_back(x);
}
void pop(int x) {
if (x == que.front())
que.pop_front();
}
int getMax() {
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue MyQueue;
vector<int> res;
for (int i = 0; i < k; i++)
MyQueue.push(nums[i]);
res.push_back(MyQueue.getMax());
for(int i = k; i < nums.size(); i++) {
MyQueue.pop(nums[i - k]);
MyQueue.push(nums[i]);
res.push_back(MyQueue.getMax());
}
return res;
}
};
347.前 K 个高频元素
实现小顶堆,也不容易,真写起来一堆问题,语法不熟和bug乱出。
priority_queue 用的是pop()和push(),回头再看看它的语法使用。
class Solution {
public:
class MyCMP{
public:
bool operator()(pair<int, int>& p1, pair<int, int>& p2) {
return p1.second > p2.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> map;
for (int i: nums) {
map[i]++;
}
// for (auto i: map)
// cout<< i.first<<"-"<<i.second<<" ";
// 开始乱写了,我也不知道pair这么用对不对
// for (map<int, int>::iterator it = map.end() - 1; it >= map.begin(); it--) { // 这得重构map的比较函数,比较value的大小才行,先用priority_queue试试
// priority_queue 是怎么比较的?
priority_queue<pair<int, int>, vector<pair<int, int>>, MyCMP> que;
for (auto i: map) {
que.push(i);
if (que.size() > k){
que.pop();
}
}
// 语法学一学
vector<int> res;
// priority_queue不提供迭代器,
for (int i = 0; !que.empty(); i++) {
res.push_back(que.top().first);
que.pop();
}
return res;
}
};
小结
栈和队列这一部分还是有些东西的,特别是几道经典题(逆波兰表达式、大小顶堆),里面设计一些c++容器和类的语法要练习,不然acm模式手写可能想不起来。
以及到现在的博客都有点水,至少回看的效率不是很高,还是需要投入精力。提高效率的方法就是把语法学会,能够快速使用。