单调队列

Posted aliencxl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调队列相关的知识,希望对你有一定的参考价值。

参考文献:https://www.jianshu.com/p/e59d51e1eef5

单调队列,顾名思义,是一种具有单调性的队列。众所周知,单调性有单调递增和单调递减两种,相应的单调队列也分为单调递增队列和单调递减队列两种。

  • 单调递增队列:保证队列头元素一定是当前队列的最小值,用于维护区间的最小值。

  • 单调递减队列:保证队列头元素一定是当前队列的最大值,用于维护区间的最大值。

实现单调队列,主要分为三个部分:

  • 去尾操作队尾元素出队列。当队列有新元素待入队,需要从队尾开始,删除影响队列单调性的元素,维护队列的单调性。(删除一个队尾元素后,就重新判断新的队尾元素)

去尾操作结束后,将该新元素入队列。

  • 删头操作队头元素出队列。判断队头元素是否在待求解的区间之内,如果不在,就将其删除。(这个很好理解呀,因为单调队列的队头元素就是待求解区间的极值)

  • 取解操作 :经过上面两个操作,取出 队列的头元素 ,就是 当前区间的极值

代码:
// 假设有 n 个元素的序列,要求解的是长度为 k 的区间的最大值
// 队列que是STL的双向队列deque
// 队列存放的是元素在序列中的序号
deque<int>que;// 双向队列
for(int i=1;i<=n;i++)
{
    while(!que.empty() && a[que.back()]<a[i])
    {
        que.pop_back();// 去尾操作
    }
    que.push_back(i);// 新元素(的序号) 入队列
    if(i>=k)// 第k个元素之后才有区间
    {
        while(!que.empty() && que.front()<i-k+1)
        {
            que.pop_front();// 删头操作 
        }
        cout<<a[que.front()]<<" ";// 取解操作
    }
}

 

64. 字符流中第一个只出现一次的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。

例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是’g’。

当从该字符流中读出前六个字符”google”时,第一个只出现一次的字符是’l’。

如果当前字符流没有存在出现一次的字符,返回#字符。

class Solution{
public:
    unordered_map<char, int> count;
    queue<char> q;
    //Insert one char from stringstream
    void insert(char ch){
        //不用去尾,因为前一个肯定比后一个先出现
        q.push(ch);
        if (++ count[ch] > 1)
        {
            //去头
            while (q.size() && count[q.front()] > 1)
            {
                q.pop();
            }
        }
    }
    //return the first appearence once char in current stringstream
    char firstAppearingOnce(){
        if (q.empty()) return #;
        return q.front();
    }
};

 

以上是关于单调队列的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6957 Maximal submatrix(悬线法 || 优先队列 || 单调栈 )

POJ 2823 Sliding Window 单调队列

单调队列与单调栈作用

单调队列题目练习

POJ 2823 Sliding Window(单调队列)

单调队列单调栈优先队列模板