代码随想录算法训练营第十三天|239. 滑动窗口最大值、347.前 K 个高频元素

文章介绍了如何使用单调队列解决滑动窗口最大值问题,以及利用小顶堆和哈希映射实现数组中前K个高频元素的查找。在单调队列的实现中,保持队列元素由大到小,每次窗口移动时更新最大值。而在高频元素问题中,自定义比较函数的小顶堆用于维护频率最高的K个元素。
摘要由CSDN通过智能技术生成

滑动窗口最大值 

题目链接:力扣

知识点:单调队列

解题思路:
需要一个队列,放进去窗口里的元素,然后随着窗口的移动,队列也一进一出,每次移动之后,队列告诉我们里面的最大值是什么。

其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。

设计单调队列时,需要保持的规则:
pop(value):
如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
push(value):
如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
front():
保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。

class MY_Queue     //为一个单调队列
{
    deque<int> MyQueue;
public:
  void pop(int value)                 //弹出元素
  {
      if(!MyQueue.empty() && value == MyQueue.front())   //窗口移除的元素value等于单调队列的出口元素
      MyQueue.pop_front();
  }

  void push(int value)                //加入元素  维护出口处的最大值
  {
      while(!MyQueue.empty() && value > MyQueue.back()) 
           MyQueue.pop_back();
          MyQueue.push_back(value);
  }

  int front()               //队列首元素,及最大值
  {
     return MyQueue.front();
  }

};


class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> Res;
        MY_Queue MQ;

        for(int i = 0; i<k; i++)   //先将前k个元素放入
            MQ.push(nums[i]);
        Res.push_back(MQ.front());

        for(int i=k ;i<nums.size();i++)
        {
            MQ.pop(nums[i-k]);
            MQ.push(nums[i]);
            Res.push_back(MQ.front());
        }

        return Res;
    }
};

前 K 个高频元素

题目链接:力扣

解题思路:
1、如何求得数组中每个元素的频率 —— map (key存放元素,value存放出现次数)
2、如何对这个频率进行排序,并求前K个高频的元素 —— 大顶堆(父亲比孩子大)、小顶堆(父亲比孩子小)遍历map中的所有元素,并以value为基准进行统计,同时该堆只维护堆中的k个元素。
这里选择小顶堆,因为遇到较大的元素时,采用pop将堆中原来的最小元素移除,再push将该元素放入,这样留下的就是较大的元素。
在CPP中,可以选用优先级队列,即priority_queue

 由于要使用小顶堆,所以需要定义一个比较函数,用于确定元素的优先级。
在这个定义中,使用了一个名为mycomparison的自定义比较函数对象。

   //小顶堆
   class mycomparison{
        public:
          bool operator()(const pair<int, int>&lhs, const pair<int, int>&rhs)
          {
              return lhs.second > rhs.second;
          }

   };

 接下来的代码中,定义了自定义的优先级队列 pri_que
priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparisom> pri_que;
具体来说,这个优先队列 pri_que 的定义包括以下几个部分:

  1. pair<int, int>表示队列中的元素类型为存储两个整数值的pair对象。每个pair对象有两个成员,分别命名为firstsecond,在这里分别表示整数值的第一个和第二个元素。

  2. vector<pair<int, int>>:作为优先队列的底层容器类型,使用vector来存储元素。这意味着优先队列中的元素将以向量的形式进行存储。

  3. mycomparison:是一个自定义的比较函数对象(Comparator),用于确定元素的优先级。在这个定义中,使用了一个名为mycomparison的自定义比较函数对象。

总的来说,这段代码定义了一个基于pair<int, int>类型的优先队列pri_que,底层使用vector作为容器,同时使用自定义的比较函数mycomparison来确定元素的优先级。

 vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int>Mymap;
        vector<int> Res(k);

        for(int i=0; i<nums.size();i++)
        {
            Mymap[nums[i]]++;           //得到各元素的频率
        }

        priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparisom> pri_que;

        for(auto it = Mymap.begin(); it != Mymap.end(); it++)
        {
            pri_que.push(*it);
            if(pri_que.size() > k)
              pri_que.pop();
        }

        for(int i=k-1;i>=0;i--)
        {
            Res[i] = pri_que.top().first;
            pri_que.pop();
        }

        return Res;
       
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值