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

239.滑动窗口最大值

思路:滑动窗口每移动一次,滑动窗口中去除第一个元素,后面加入一个元素,获得一次滑动窗口的最大值。因此我们自定义pop、push、getMaxvalue函数,将滑动窗口内的元素排列成单调队列。单调队列的头部一直是最大元素,当滑动窗口移动时,我们需要向单调队列中push元素,当我们push的元素比队列中的尾部元素大时,就把队列的尾部元素pop出去,然后再将元素push进去,因为我们只需要滑动窗口中最大的元素。当需要pop的元素和头部元素相同时,将头部元素pop出去,因为如果不相同说明此时需要pop的元素不是滑动窗口中最大的元素,在push的过程中就被pop出去了,然后在每次移动过程中,都取滑动窗口的头部,即最大值,遍历数组,收集到滑动窗口最大值的数组返回。

class Solution {
public:
        //DIY pop函数 
        //DIY push函数
        //DIY getMaxvalue函数
        //DIY 单调队列
    class MyQueqe
        {
            public:
            deque<int> q1;
            void pop(int val)
            {
                if(!q1.empty() && val==q1.front())
                {
                    q1.pop_front();
                }
            }
            void push(int val)
            //从后往前删
            {
                while(!q1.empty()&&val>q1.back())
                {
                    q1.pop_back();
                }
                q1.push_back(val);
            }
            int getMaxvalue()
            {
                return q1.front();
            }
        };

    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQueqe q1;
        vector<int> result;
        for(int i =0;i<k;i++)
        {
            q1.push(nums[i]);
        }
        result.push_back(q1.getMaxvalue());
        for(int i =k;i<nums.size();i++)
        {
            q1.pop(nums[i-k]);
            q1.push(nums[i]);
            result.push_back(q1.getMaxvalue());
        }
        return result;
    }
};

345.前K个高频元素

思路:利用map,获取整数数组中元素出现的频率。然后构造一个小顶堆,即堆的顶部一直是最小的元素,这样方便我们pop出去,在堆内部留下大的元素。最后构造一个k长度的数组,从后向前填充元素,填充的元素为小顶堆的头部。

class Solution {
public:
        //小顶堆
        class mycompare{
            public:
            bool operator()(pair<int,int>&p1,pair<int,int>&p2)
            {
                return p1.second>p2.second;
            }
        };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        priority_queue<pair<int,int>,vector<pair<int,int>>,mycompare> pri_que;
        unordered_map<int,int> map;
        for(int i =0;i<nums.size();i++)
        {
            map[nums[i]]++;
        }
        for(unordered_map<int,int>::iterator it=map.begin();it!=map.end();it++)
        {
            pri_que.push(*it);
            if(pri_que.size()>k)
            {
                pri_que.pop();
            }
        }
        vector<int> result(k);
        for(int i=k-1;i>=0;i--)
        {
            result[i] = pri_que.top().first;
            pri_que.pop();
        }
        return result;


    }
};

收获:

1、学会了使用单调队列,在寻找滑动窗口内部的最大值时,判断滑动窗口中比push的那个元素小的元素是没意义的,因此在push之前,先把比它小的元素pop出去(从后往前)。

2、学会了使用小顶堆,利用priority_queue构建优先队列,根据自己写的compare类,类内重载()的return来控制大顶堆和小顶堆,利用小顶堆,当堆的元素超出k时,移出栈顶元素,此时栈顶元素为最小的元素,因此最后留下的元素都是最大的元素。由于栈底的元素才是最大的元素,所以定义的数组从后往前填充,顺序就为从大到小了。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值