239.滑动窗口最大值
链接:LeetCode239.滑动窗口最大值
思路:
刚开始假设使用的是栈,当栈空时元素入栈。当栈不为空且当前元素小于栈顶元素,元素入栈。当栈不为空,当前元素大于栈顶元素,栈顶出栈直到当前元素小于栈顶元素。当当前的元素下标i+1>=k时,可以寻找窗口内的最大元素,此时栈底元素为当前窗口最大值。此时栈结构已经不满足当前的操作,既可以从顶部删除插入元素又可以从底部取出元素,可以选取deque作为该题的数据结构。为了满足当前的最大元素在当前的窗口内,需要将元素和对应的下标位置做一个映射。将其存储到pair<int,int>中。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//用队列
deque<pair<int,int>> qu;vector<int> ans;
for(int i=0;i<nums.size();++i){
while(!qu.empty() && qu.back().first<=nums[i]) qu.pop_back();
qu.push_back(pair<int,int>{nums[i],i});
//保证在同一个窗口
if(i+1 >= k) {
while(!qu.empty() && qu.front().second<i+1-k) qu.pop_front();
ans.push_back(qu.front().first);
}
}
if(nums.size()<k) ans.push_back(qu.front().first);
return ans;
}
};
347.前K个高频元素
- 将元素和其出现的次数做一个映射。按照元素出现的次数从大到小进行排序。输出前K个元素。
- 借用堆排序的思想,选取优先级队列作为作为本题的数据结构。并且排序方法为:以key:value;中的value值为依据的小根堆。(为什么选用小根堆呢?因为大根堆只能满足第一个元素是所有元素中最大的,而不能保证其余k-1个元素是次大的)。
错误代码
class Solution {
public:
typedef pair<int,int> pa;
vector<int> topKFrequent(vector<int>& nums, int k) {
//映射元素和其出现的次数
unordered_map<int,int> ma;
for(const int&num:nums) ++ma[num];
if(nums.size()<=k) return nums;
//开始寻找出现频率前k高的元素
priority_queue<pa,vector<pa>,less<pa>> qu;//小根堆
for(auto it = ma.begin();it!=ma.end();++it) {
if(qu.size()<k) qu.push(pa{it->second,it->first});
else if(it->second>qu.top().first)
{qu.pop();qu.push(pa{it->second,it->first});}
}
vector<int> ans;
while(k--) {ans.push_back(qu.top().second);qu.pop();}
return ans;
}
};
代码分析
- 写的第一版代码中,是将元素出现的次数作为key值,元素的数值作为value值存储在pair中再将其加入到优先级队列中(因为优先级队列是按照key值进行排序的)。但是却忽略了一种很关键的情况:不同的数值出现的次数一致,这种情况下只能保存一个键值对,会自动舍弃掉其它元素。改正方法就是:元素的数值作为key值,出现的次数作为value值。写一个按照value值排序的小根堆。
正确代码
class Solution {
public:
typedef pair<int,int> pa;
class myfun{
public:
//必须将函数设置成public不然外部无法访问
bool operator ()(const pa&p1,const pa&p2){
return p1.second>p2.second;//小根堆
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
//映射元素和其出现的次数
unordered_map<int,int> ma;
for(const int&num:nums) ++ma[num];
if(nums.size()<=k) return nums;
//开始寻找出现频率前k高的元素
priority_queue<pa,vector<pa>,myfun> qu;//小根堆
for(auto it = ma.begin();it!=ma.end();++it) {
//cout << it->first<<" "<<it->second;
if(qu.size()<k) qu.push(*it);
else if(it->second > qu.top().second) {qu.pop();qu.push(*it);}
}
vector<int> ans(k,0);int in=0;
while(k--) {ans[in++] = qu.top().first;qu.pop();}
return ans;
}
};