239. 滑动窗口最大值
要点
- 需要的队列主要实现三个方法:
pop(val),push(val),get_max() - 优先级队列 每次
pop后会重新调整堆,使得最大值在出口位置;不适用与本题因为由于FIFO的特性在维护滑动窗口时,窗口的pop操作受阻 - 维护队列未必要把所有窗内元素保持在队内,因此实现一个单调队列
lower_queue中 1. 元素的先后顺序同数组顺序 2. 单调递减- 实现
push()时,为了保证单调性,将所有比插入数小的元素pop出,他们不可能作为某个窗口max输出
单调队列
class Solution {
private:
class lower_queue{
deque<int> dq;
public:
void pop(int val) {
if (!dq.empty() && val == dq.front()) {
dq.pop_front();
}
}
void push(int val) {
while (!dq.empty() && dq.back() < val) {
dq.pop_back();
}
dq.push_back(val);
}
int get_max() {
return dq.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
lower_queue que;
vector<int> res;
for (int i = 0; i < k; ++i) {
que.push(nums[i]);
}
res.push_back(que.get_max());
for (int j = k; j < nums.size(); ++j) {
que.pop(nums[j-k]);
que.push(nums[j]);
res.push_back(que.get_max());
}
return res;
}
};
总结
时间复杂度为O(n),空间复杂度为O(k)
347. 前 K 个高频元素
要点
- 优先级队列初始化:
priority_queue< type, container, function > - 仿函数
greater,less都是结构体,体内重载()来模拟函数操作。两者都在头文件functional内 blog.csdn.net/jay_zzs/art…
- 优先级队列(堆)中的
cmp函数与通常排序的cmp函数大小比较相反
- 优先级队列取首元素为
top(), 不是front() for (auto it : map)it是pair元素,不是迭代器
优先级队列
class Solution {
public:
//实现一个比较的仿函数,小顶堆
struct cmp{
bool operator() (const pair<int, int>& lp, const pair<int, int>& rp){
return lp.second > rp.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>>, cmp> que;
for (auto it : map) {
que.push(it); //bug! 不用解引用
if (que.size() > k) que.pop();
}
vector<int> res(k);
for (int i = k-1; i >= 0; i--) {
res[i] = que.top().first;
que.pop();
}
return res;
}
};
总结
堆的更新时间复杂度为O(logn),建堆为O(n),此题的时间复杂度为O(nlogk)