题目链接 : 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();
- }
- };
-
- };
题目链接:
思路分析:
视频和更详细的文字讲解(代码随想录):
- 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
size() ; i++){ - temp[ nums[i] ]++;
- }
- // 排序使用 ,小顶堆(优先级队列)
- priority_queue
int, int>, vectorint, 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(); //将最小的值出队
- }
- //入队,并排序
-
- }
- //将队列中的数据导入ret
- vector<int>ret(k);
- for( int i=k-1 ; i>=0 ;i-- ){
- ret[i]=pq.top().first;
- pq.pop();
- }
- return ret;
- }
- };