day13打卡
时间复杂度:O(N),空间复杂度:O(K)
第一想法:只能想出暴力解法
看了题解:用deque维护一个单调队列,
-
用一个while循环维持队列的单调性:队列中有元素且元素末尾的大小小于等于当前i位置的元素就把队列末尾的元素pop掉,直到队列末尾没有元素或者队列末尾的元素大于当前位置i的元素。
-
窗口正常滑动即可(就是正常向队列中push元素),但是如果当队列最大值元素(首部元素)已经出了窗口,别忘记pop掉队列首部的元素。如何判断,即当
i-队列.front()
>=k
时就是队首元素离开窗口的时候。 -
记录答案,从第一次达到滑动窗口最大值时(即,i >= k-1),就开始记录答案。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
deque<int> dq;
for(int i = 0; i < nums.size(); i++)
{
//保证单调性
while(!dq.empty() && nums[dq.back()] <= nums[i]) dq.pop_back();
dq.push_back(i);
//离开队首就pop
if(i - dq.front() >= k) dq.pop_front();
//记录答案
if(i >= k-1) ans.push_back(nums[dq.front()]);
}
return ans;
}
};
时间复杂度:O(NlogK),空间复杂度:O(N)
第一想法:用优先队列+哈希表
困难:没有实现
看完题解:哈希表存储元素出现频率+创建k个大小的小堆,找出k个出现频率最大的元素(堆中是从小到大排序的)+保存答案
- 哈希表存储十分简单
- 用迭代器变量哈希表元素(
it.second
),如果超出k个就把最小的pop掉即可 - 保存答案时,倒着保存,题目要求是前k个高频元素
class Solution {
class myCmp
{
public:
bool operator()(const pair<int, int>& l, const pair<int, int>& r)
{return l.second > r.second;}
};
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
//存入哈希表
unordered_map<int, int> map;
for(auto& e : nums) map[e]++;
//创建小堆
priority_queue<pair<int, int>, vector<pair<int, int>>, myCmp> pq;
for(unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++)
{
pq.push(*it);
//如果堆的大小大于k,把堆内最小的元素pop掉
if(pq.size() > k) pq.pop();
}
//记录答案
vector<int> ans(k);
for(int i = k-1; i >= 0; i--)
{
ans[i] = pq.top().first;
pq.pop();
}
return ans;
}
};