文档讲解:代码随想录 (programmercarl.com)
视频讲解:单调队列正式登场!| LeetCode:239. 滑动窗口最大值_哔哩哔哩_bilibili
状态:没做出来
思路上还是很复杂的,因为这题的解法是要自定义一个单调减队列,也就是说,如果入队的时候前面有比当前入队的值小的数,都要出队,考虑到不可能队列里的元素都比当前入队的元素的值要小,所以这个时候出队必须要从队尾出,当然由于是滑动窗口所以队列中的最大值有被弹出的可能,所以还是要保留队头出队的功能。
用双端队列可以很好地解决这个问题,因为双端队列就是从队列两端出队的。而且,容器适配器stack,queue都是由双端队列实现的,也就是deque。
为什么想到用队列?滑动窗口的机制本身就很像队列,队头出,队尾进。
class Solution {
public:
void pop(deque<int>& deq,int value){
if(!deq.empty() && value == deq.front()){
deq.pop_front();
}
}
void push(deque<int>& deq,int value){
while(!deq.empty() && value > deq.back()){
deq.pop_back();
}
deq.push_back(value);
}
int getMaxValue(deque<int>& deq){
return deq.front();
}
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> deq;
for(int i = 0;i < k;i++){
push(deq,nums[i]);
}
vector<int> result;
result.push_back(getMaxValue(deq));
for(int i = k;i < nums.size();i++){
pop(deq,nums[i-k]);
push(deq,nums[i]);
result.push_back(getMaxValue(deq));
}
return result;
}
};
文档讲解:代码随想录 (programmercarl.com)
视频讲解:优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode:347.前 K 个高频元素_哔哩哔哩_bilibili
状态:没做出来
这道题的思路其实不难,用map将数组中所有元素以及出现次数都记录下来,然后把这些数据,导入另一种自带排序功能的容器,排一下序找前k个就行。
在leetcode上看到有人用vector来承接map的数据,当然可以,但是这样排序把所有元素都排了,其实并不需要把所有元素都排序,可以用小顶堆实现。
为什么是小顶堆?1. 在C++中priority_queue可以实现小顶堆。有现成的数据结构。2.只需要保持小顶堆里的是前k个高频元素即可,多余的可以出队。3. 每次出队都是在队头,所以队头应该是频率最低的元素。
这题真正的难点是语法,很难理解。等后面统一总结的时候把它搞定。现在任然一知半解。
class Solution {
public:
static bool cmp(const pair<int,int> &lhs,const pair<int,int> &fls){
return lhs.second > fls.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> umap;
for(int i = 0 ;i < nums.size();i++){
umap[nums[i]]++;
}
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)> p_queue(&cmp);
for(unordered_map<int,int>::iterator it = umap.begin();it != umap.end();it++){
p_queue.push(*it);
if(p_queue.size() > k){
p_queue.pop();
}
}
vector<int> result(k);
for(int i = k-1;i >=0;i--){
result[i] = p_queue.top().first;
p_queue.pop();
}
return result;
}
};