239. 滑动窗口最大值
自己构建一个队列应实现pop、push、和max功能;弹入弹出元素很好实现,问题是如何获取滑动窗口的最大值。如果暴力循环的话时间复杂度将是o(n*k)。
因为我们的目的是获取到滑动窗口的最大值,而不是保存当前的窗口,所以我们没必要维护当前窗口的所有值,只需要保证最大值在窗口的出口处,这样我们直接调用函数deque.front()就可以获取了。那么就有思路了,只需要在放入元素的时候,把队列内小于该元素的值全部移除就可以了。在移除元素时判断一下队列出口处的元素是否与我们要移除的元素相同,如果不同那说明我们在执行push时已经把该元素移除了,就不用移除了;如果相同则移除该元素。
class Solution {
private:
class Myque {
public:
deque<int> que;
void pop(int val) {
if (!que.empty() && que.front() == val) que.pop_front(); //如果队头元素(最大值)等于要移除的元素就移除
}
void push(int val) {
while (!que.empty() && que.back() < val) { //把队内所有比新入队小的元素弹出,保证单调性
que.pop_back();
}
que.push_back(val); //然后在入队新元素
}
int _front() {
return que.front(); //返回队头元素(即是当前滑动窗口最大值)
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
Myque que;
vector<int> res;
for (int i = 0; i < k; ++i) { //把前三个元素入队
que.push(nums[i]);
}
res.push_back(que._front()); //记录当前窗口最大值
for (int i = k; i < nums.size(); ++i) {
que.push(nums[i]); //移除窗口开头元素
que.pop(nums[i - k]); //加入下一个元素
res.push_back(que._front()); //记录当前窗口最大值
}
return res;
}
};
347.前 K 个高频元素
先把元素都存放在map里得到每个元素的频率,再创建一个小顶堆,里面只放k个元素,最后大顶堆里的k个元素就是 前k个高频元素。
class Solution {
public:
class myComprisom { //重新定义排序,从小到大
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; //把数据存到map里,重复出现的value+1;
for (int i = 0; i < nums.size(); i++)
{
map[nums[i]]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, myComprisom> pri_que; //定义大小为k优先队列,只存放value前三大的数
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> res(k);
// for (int i = 0; i < k; i++) 因为结果不用顺序所以倒序输出也可以
for (int i = k-1; i >=0; i--) //把队列里的key存到res里
{
res[i] = pri_que.top().first;
pri_que.pop();
}
return res;
}
};