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


    文章目录

      • 对应力扣的题目链接
      • 思路分析
      • 解决方案

    问题一 、239. 滑动窗口最大值

    题目链接  239. 滑动窗口最大值 - 力扣(LeetCode)

    思路分析 :

                  1、可能首先想到的是暴力破解 ,每一个区间,遍历一遍,找到最大值。将其搜集起来。

                  2、单调队列的思想 ,每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数                      值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。

                  3、 当然这个队列是没有的,具体功能需要我们自己实现。

    单调队列的实现(  基于一个双向队列  deque  可以对对头和队尾进行操作 )
    my_push( )   入队 :

    入队之前和队列中元素进行比较,如果队列中的元素比要入队的元素小,则将其出队。

    这样我们队列的对头元素总是最大值,然后我们滑动窗口移动的时候,每次都从对头拿去窗口的最大值。

    1. void my_push( int value ){
    2. while( !my_queue.empty() && my_queue.back() < value){
    3. my_queue.pop_back();
    4. }
    5. my_queue.push_back( value );
    6. }
    7. // my_queue 是我们定义的一个私有成员, 他是 deque 类型

    my_pop( )   出队 :

    因为我们在入队的时候,就已经将较小的元素出队了。

    所以这里我们处理的是,如果窗口移除的元素value等于单调队列的出口元素,则将其出队。

    1. //出队
    2. void my_pop(int value){
    3. //当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值
    4. if(!my_queue_.empty() && value==myDeque_.front()){
    5. myDeque_.pop_front() ;
    6. }
    7. }

    视频和更详细的文字讲解(代码随想录)

    代码随想录

    具体解决方案:

    1. class Solution {
    2. public:
    3. vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    4. myDeque myDeque_;
    5. vector< int >data;
    6. if( nums.size() < k ) return data;
    7. //先放入前k个元素
    8. for( int i = 0 ; i < k ; i++ ){
    9. myDeque_.my_push(nums[i]);
    10. }
    11. //找到前k个的最大值
    12. data.push_back( myDeque_.getMax() );
    13. for(int i=k ; i< nums.size() ; i++ ){
    14. myDeque_.my_pop( nums[i-k] ); //
    15. myDeque_.my_push( nums[i] );
    16. data.push_back( myDeque_.getMax() );
    17. }
    18. return data;
    19. }
    20. private:
    21. class myDeque{
    22. public:
    23. deque< int >myDeque_; //定义一个双向队列
    24. //出队
    25. void my_pop(int value){
    26. //当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值
    27. if(myDeque_.empty()!=true && value==myDeque_.front()){
    28. myDeque_.pop_front() ;
    29. }
    30. }
    31. //入队
    32. void my_push(int value){
    33. while( myDeque_.empty()!=true && value > myDeque_.back() ){
    34. myDeque_.pop_back();
    35. }
    36. myDeque_.push_back(value);
    37. }
    38. int getMax(){
    39. return myDeque_.front();
    40. }
    41. };
    42. };

    问题二 、347.前 K 个高频元素 

    题目链接:

    347. 前 K 个高频元素 - 力扣(LeetCode)

    思路分析:

    • 遇到一个数出现的次数,我们首先想到 使用map 这个容器,key 记录要计算的数,value 出现的次数
    • 优先级队列(底层是实现是一个堆),将map中的数据进行排序,采用小顶堆
    • 最后反向输入到需要返回的数组中

    视频和更详细的文字讲解(代码随想录):

    代码随想录

    解决方案:

    1. class Solution {
    2. public:
    3. //自定义比较函数
    4. class MyCompare{
    5. public:
    6. bool operator()(const pair<int ,int>&left , const pair<int ,int>&right){
    7. return left.second > right.second;
    8. }
    9. };
    10. vector<int> topKFrequent(vector<int>& nums, int k) {
    11. // if(nums.size() < k ) return ret;
    12. unordered_map< int ,int >temp;
    13. // key 是数字, value是出现的次数
    14. for(int i=0 ; isize() ; i++){
    15. temp[ nums[i] ]++;
    16. }
    17. // 排序使用 ,小顶堆(优先级队列)
    18. priority_queueint, int>, vectorint, int>>, MyCompare > pq;
    19. //将map中的数据放入优先级队列,并从小到大排序
    20. for(unordered_map<int,int>::iterator it = temp.begin() ; it!=temp.end() ; it++){
    21. pq.push(*it);
    22. if(pq.size() >k ){
    23. pq.pop(); //将最小的值出队
    24. }
    25. //入队,并排序
    26. }
    27. //将队列中的数据导入ret
    28. vector<int>ret(k);
    29. for( int i=k-1 ; i>=0 ;i-- ){
    30. ret[i]=pq.top().first;
    31. pq.pop();
    32. }
    33. return ret;
    34. }
    35. };

  • 相关阅读:
    StartCoroutine/yield 返回模式在 Unity 中到底如何工作?
    享元模式Flyweight
    【算法】一类支持向量机OC-SVM(1)
    神经网络的整个过程包括,神经网络的实现过程
    栈简介、手写顺序栈、手写链栈和栈的应用
    用三智者交易策略澳福加减仓轻松盈利,就是这么厉害
    走两步!AI通过步态诊断帕金森;从入门到如土·AI绘画中文指南;超好用的视频补帧软件;YOLO7人脸检测实现;前沿论文 | ShowMeAI资讯日报
    环境配置04:Pytorch下载安装
    MySQL 自建数据库慢日志分析
    bilibili快速升满级(使用Docker 容器脚本)
  • 原文地址:https://blog.csdn.net/qq_62989250/article/details/134283506