代码随想录刷题Day30
滑动窗口最大值
这道题需要使用的是优先队列/堆的数据结构,因为它是要不断地记录一串数据序列中的最大值,像这样的问题,堆可以自动维护堆顶元素是序列里的最大值/最小值。
这道题的思路是:
- 先把数组前k个数以pair<value,index>的形式放入堆中,把堆顶元素的value值放入答案向量res中;
- 对剩下的元素,依次比遍历
- 每次遍历时候,把当前元素的<value,index>放入堆中
- 从堆中取出堆顶元素,如果堆顶元素的index不在[i-k+1,i]这样一个范围内,就让堆pop掉堆顶元素,直到堆顶元素的index在[i-k+1,i]这个区间位置,并把堆顶元素的value值放入答案向量res中
- 不断循环上述两个步骤,直到所有元素遍历完
- 返回res结果
代码如下:
class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> res;int n = nums.size();priority_queue<pair<int,int>> a; //默认先比较pair第一个元素,如果相等就比较下一个元素,第一个是value,第二个元素是Index.默认是大顶堆for(int i = 0;i<nums.size()&&i<k;i++){ //先把优先队列k个元素填充好a.emplace(nums[i],i); //emplace函数可以用来创建一个优先队列的对象,并放入队列中}//第一个K序列里的最大的元素值res.push_back(a.top().first);//挨个遍历数组中的元素for(int i = k;i<n;i++){a.emplace(nums[i],i);while(a.top().second < i - k + 1){ //不断获取堆顶元素,直到堆顶元素的索引值在[i-k+1,i]范围内a.pop();}res.push_back(a.top().first);}return res;}
};
写代码发现,这里使用一个int n = nums.size()比直接在循环遍历时候直接让i<nums.size()会少花不少时间。
前K个高频元素
这道题在有了上面这题的基础上,继续做的话,会很容易想到思路,这里也是使用优先队列的方式。
先对数组中的元素借助map进行次数的统计,接着使用优先队列的方式,对map中的<次数,值>重新按照次数的大小降序排列,最后从优先队列中pop出k个值,就可以得到出现次数为前k的元素值,代码如下:
class Solution {
public:vector<int> topKFrequent(vector<int>& nums, int k) {//使用map统计不同值出现的次数map<int,int> value_cnt_map;int n = nums.size();for(int i = 0;i<n;i++){if(value_cnt_map.find(nums[i])!= value_cnt_map.end()){value_cnt_map[nums[i]]++;}else{value_cnt_map[nums[i]] = 1;}}//使用优先队列对(次数,值)按照出现次数降序排列priority_queue<pair<int,int>> cnt_value_heap;for(map<int,int>::iterator it = value_cnt_map.begin();it!= value_cnt_map.end();++it){cnt_value_heap.emplace(it->second,it->first);}//k次提取堆顶的值,也就是出现次数前k大的值放入答案ans中vector<int> ans;while(k--){ans.push_back(cnt_value_heap.top().second);cnt_value_heap.pop();}return ans;}
};
栈与队列系列刷题小结
该系列刷题,我重新回顾了栈和队列的一些基础用法,以及STL中相关的数据结构的使用。
刷题主要有三类:
- 栈和队列的基础性质:
- 使用两个栈来实现队列,主要是如何用栈的LIFO(Last in,first out 后入先出)的性质去模拟队列的FIFO(First in,first out 先入先出),这里可以使用一个栈作为push站,一个栈作为pop/top的访问栈;
- 使用两个队列来实现栈,对于栈的pop或者是top,就只能是从队列中挨个把元素取出来放到另一个队列中,直到取到队底的元素,就作为栈顶的元素弹出或者访问。
- 栈系列的经典题目
- 括号匹配
- 删除字符串中的所有相邻重复项
- 后缀表达式
- 这些题目,应该算是经典而又基础的题了,只是要注意,在使用栈的时候,要注意空栈的情况,以及什么情况下栈中的元素要出栈,什么情况下要入栈,以及要注意出栈元素的顺序和实际入栈的顺序是相反的(这在表达式那道题有所体现)
- 优先队列
- 这个知识点,感觉更属于堆的知识,不过是会用到队列的一些基本操作,比如push,pop,top,emplace这些
- 滑动窗口最大值
- 前K个高频元素
- 这些题,基本思路比较好想到,只是会在使用pair,或者map,以及emplace()这样的函数有些生疏。