文章目录
-
- 对应力扣的题目链接
- 思路分析
- 解决方案
问题一 、239. 滑动窗口最大值
题目链接 : 239. 滑动窗口最大值 - 力扣(LeetCode)
思路分析 :
1、可能首先想到的是暴力破解 ,每一个区间,遍历一遍,找到最大值。将其搜集起来。
2、单调队列的思想 ,每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数 值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。
3、 当然这个队列是没有的,具体功能需要我们自己实现。
单调队列的实现( 基于一个双向队列 deque 可以对对头和队尾进行操作 )
my_push( ) 入队 :
入队之前和队列中元素进行比较,如果队列中的元素比要入队的元素小,则将其出队。
这样我们队列的对头元素总是最大值,然后我们滑动窗口移动的时候,每次都从对头拿去窗口的最大值。
void my_push( int value ){while( !my_queue.empty() && my_queue.back() < value){my_queue.pop_back();}my_queue.push_back( value );
}// my_queue 是我们定义的一个私有成员, 他是 deque 类型
my_pop( ) 出队 :
因为我们在入队的时候,就已经将较小的元素出队了。
所以这里我们处理的是,如果窗口移除的元素value等于单调队列的出口元素,则将其出队。
//出队void my_pop(int value){//当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值if(!my_queue_.empty() && value==myDeque_.front()){myDeque_.pop_front() ;}}
视频和更详细的文字讲解(代码随想录)
代码随想录
具体解决方案:
class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {myDeque myDeque_;vector< int >data;if( nums.size() < k ) return data;//先放入前k个元素for( int i = 0 ; i < k ; i++ ){myDeque_.my_push(nums[i]);}//找到前k个的最大值data.push_back( myDeque_.getMax() );for(int i=k ; i< nums.size() ; i++ ){myDeque_.my_pop( nums[i-k] ); //myDeque_.my_push( nums[i] );data.push_back( myDeque_.getMax() );}return data;}private:
class myDeque{public:deque< int >myDeque_; //定义一个双向队列//出队void my_pop(int value){//当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值if(myDeque_.empty()!=true && value==myDeque_.front()){myDeque_.pop_front() ;}}//入队void my_push(int value){while( myDeque_.empty()!=true && value > myDeque_.back() ){myDeque_.pop_back();}myDeque_.push_back(value);}int getMax(){return myDeque_.front();}
};};
问题二 、347.前 K 个高频元素
题目链接:
347. 前 K 个高频元素 - 力扣(LeetCode)
思路分析:
- 遇到一个数出现的次数,我们首先想到 使用map 这个容器,key 记录要计算的数,value 出现的次数
- 优先级队列(底层是实现是一个堆),将map中的数据进行排序,采用小顶堆
- 最后反向输入到需要返回的数组中
视频和更详细的文字讲解(代码随想录):
代码随想录
解决方案:
class Solution {
public:
//自定义比较函数
class MyCompare{public:bool operator()(const pair<int ,int>&left , const pair<int ,int>&right){return left.second > right.second;}
};vector<int> topKFrequent(vector<int>& nums, int k) {// if(nums.size() < k ) return ret;unordered_map< int ,int >temp;// key 是数字, value是出现的次数for(int i=0 ; i<nums.size() ; i++){temp[ nums[i] ]++;}// 排序使用 ,小顶堆(优先级队列)priority_queue<pair<int, int>, vector<pair<int, int>>, MyCompare > pq;//将map中的数据放入优先级队列,并从小到大排序for(unordered_map<int,int>::iterator it = temp.begin() ; it!=temp.end() ; it++){pq.push(*it);if(pq.size() >k ){pq.pop(); //将最小的值出队}//入队,并排序}//将队列中的数据导入retvector<int>ret(k);for( int i=k-1 ; i>=0 ;i-- ){ret[i]=pq.top().first;pq.pop();}return ret;}
};