day 13 队列

文章详细介绍了三种不同的队列类型:普通队列、双端队列和优先队列。普通队列不支持迭代器访问,而双端队列可以在两端添加和删除元素。优先队列通常用于寻找最大或最小元素,但不能直接通过迭代器访问。文章还通过代码示例展示了如何使用队列解决滑动窗口最大值问题以及找出数据流中的前K个高频元素。
摘要由CSDN通过智能技术生成
  1. queue 队列 不可以通过迭代器访问

     	front()	返回第一个元素的引用。
     	back()	返回最后一个元素的引用。
     	push() 在序列的尾部添加一个元素。
     	pop()  移除容器头部的元素。
    
  2. deque 双端队列 可以通过迭代器访问

     	front()	返回第一个元素的引用。
     	back()	返回最后一个元素的引用。
     	
     	push_back()	在序列的尾部添加一个元素。
     	push_front()	在序列的头部添加一个元素。
     	
     	pop_back()	移除容器尾部的元素。
     	pop_front()	移除容器头部的元素。
    
  3. priority_queue 优先队列 不可以通过迭代器访问

     	top()  返回第一个元素的引用。
     	push()
     	pop() 移除 priority_queue 容器适配器中第一个元素。
     	
     	priority_queue<int, vector<int>, less<int>> pq;  // 最大堆
     	priority_queue<int, vector<int>, greater<int>> pq;  // 最小堆
     	priority_queue<ListNode*, vector<ListNode*>, cmp> pq; 
     	
     	priority_queue自定义函数的比较与sort正好是相反的
     	
        也就是说,如果你是把大于号作为第一关键字的比较方式,那么堆顶的元素就是第一关键字最小的
     	struct cmp{
     	    bool operator()(const ListNode* a, const ListNode* b){
     	         return a->val > b->val;
     	    }
     	};
    

239. 滑动窗口最大值

题目:给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。

思路:
1. 需要维持一个有可能成为窗口最大元素就可以
2. 窗口就是先进先出 那么我们需要一个队列
3. 假定 当前元素为 1 下一个存进来地元素 是5 那么 1就不可能是该窗口的最大值
所以这个队列里的元素保持单调递减 5 4 3 2 1
5出队 4 是最大值 4 出队 3是最大值
4. 那么新进队的元素应该与队尾元素进行比较,队尾元素小就要一直出队,从队尾出队,使用到双头队列 deque
5. 具体操作: 维持一个单调递减的队列,如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止,移除元素时,如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int>q;
        vector<int>result;
        int start = 0;
        int end = start;
        while(end < nums.size()){
            while(!q.empty() && nums[end] > q.back()){
                q.pop_back();
            }
            q.push_back(nums[end]);   //保证队列单调
            end++;
            if(end - start == k){
                result.push_back(q.front());
                if(nums[start] == q.front()){  //维持当前窗口的最大值
                    q.pop_front();
                }
                start++;
            }
        }
        return result;

    }
};

347. 前 K 个高频元素

思路: 1. 用map 进行统计 2. 用最大最小堆进行排序
关键: 用最大堆还是最小堆
当元素元素特别多,但是k很小时,维持一个k的最小堆来省空间。小顶堆每次将最小的元素弹出,最后小顶堆里积累的就是前k个最大元素。

class Solution {
public:
    struct cmp{
        bool operator()(const pair<int, int>&a, const pair<int, int>&b){
            return a.second > b.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int>mp;
        for(int i = 0; i < nums.size(); i++){
            mp[nums[i]]++;
        }
    
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp>q;

        for(pair<int, int>x : mp){
            if(q.size() >= k && q.top().second < x.second){
                q.pop();
                q.push(x);
            }else if(q.size() < k){
                q.push(x);
            }
        }
        vector<int>reslut;
        while(!q.empty()){
            reslut.push_back(q.top().first);
            q.pop();

        }
        return reslut;
    }
};

BM48 数据流中的中位数

class Solution {
  public:
    priority_queue<int, vector<int>, less<int>>m_in;  //放着小于等于中位数的元素
    priority_queue<int, vector<int>, greater<int>>m_ax; //大于中位数
    void Insert(int num) {
        if (m_in.empty() || m_in.top() >= num) {
            m_in.push(num);   
            //我们要维持min.size()-max.size()<2;
            if (m_in.size() - m_ax.size() >= 2) { 
                m_ax.push(m_in.top());
                m_in.pop();
            }
        } else {
            m_ax.push(num);
            if (m_ax.size() - m_in.size() >= 1) {
                m_in.push(m_ax.top());
                m_ax.pop();
            }
        }
    }

    double GetMedian() {
        if(m_in.size() - m_ax.size() == 1) return double(m_in.top());
        return (m_in.top() + m_ax.top())/2.0;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值