The application of monotonic queues: the sword refers to Offer 59 - II. The maximum value of the queue double-ended queue (with pictures and texts) step-by-step detailed guide

Topic information

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1


Sample

Example 1:
输入: 
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]
Example 2:
示例 2:

输入: 
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出: [null,-1,-1]

limitation factor

限制:

1 <= push_back,pop_front,max_value的总操作数 <= 10000
1 <= value <= 10^5

Ideas:

The title requires that the amortized time complexity of insertion, deletion, and maximum value are all O(1). Insertion and deletion are simple. The key is how to find the maximum time complexity of O(1). If it is violent, you need to traverse the elements of the queue once to find the maximum value, and the time complexity of that is O(n).

Next, I used the practice of changing space for time, and introduced a double-ended queue to assist in finding the maximum value.

insert image description here

接下来用一组数据举一个例子:3 4  1  5

Step 1:

insert image description here

Step 2:

insert image description here

Step 3:

insert image description here

Step 4:

insert image description here

Summarize:

When inserting, it can be found that the max at any time can be obtained directly at the head of the double-ended queue, so the time complexity O(1) for max is realized.

Code

Next, let's take a look at the code of the specific implementation. It is not easy to make. If you understand it, why not give it a three-link?

class MaxQueue {
    
    
    //q是普通队列,d是双端队列
Queue<Integer> q;
Deque<Integer> d;

    public MaxQueue() {
    
    
        //初始化
        
        q=new LinkedList<> ();
        d=new LinkedList<> ();
    }

    public int max_value() {
    
    
        //如果双端队列为空返回-1,不然就返回双端队列的队头元素
        if(d.isEmpty ()){
    
    
            return -1;
        }
        return  d.peekFirst ();
    }

    public void push_back(int value) {
    
    
        //当双端队列不为空并且它的队尾元素<待插入元素时,将队头元素出队列
        while (!d.isEmpty () && d.peekLast ()<value){
    
    
            d.pollLast ();
        }
        //两个条件有一个不满足的话,正常插入
        d.offerFirst (value);
        q.offer (value);
    }

    public int pop_front() {
    
    
        //普通队列为空返回-1
        if (q.isEmpty ()){
    
    
            return  -1;
        }
        //先获取普通队列的队头,如果队头和双端队列的队列相等的话,那么双端队列的队列也要出队列。
        int ans=q.poll ();
        if(ans==d.peekFirst ()){
    
    
            d.pollFirst ();
        }
        return  ans;
    }
}

Guess you like

Origin blog.csdn.net/guankunkunwd/article/details/122619518