队列的最大值

本文探讨了队列这种数据结构,并重点讲解如何在保持队列基本操作的同时,设计一个数据结构以常数时间复杂度获取当前队列内的最大值。通过巧妙的双端队列实现,可以在不牺牲效率的情况下,实时获取队列内的最大元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                                                                                                  点击此处返回总目录

 

来自:剑指offer 59题

 

【题目】

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

 

 

【分析】

前面我们做过一个o(1)时间内返回栈内最大或最小元素的题目。就是使用了两个栈,第二个栈维护这前n个元素的最小值,当出栈的时候最小值也跟着出栈。

 

我们这里也一样,使用两个队列,一个是存放数值,这样本身入队和出队的时间是o(1)。而另一个栈,存放剩余元素的最小值。

比如:

 

                                  

 

上面是数值队列,下面是最大值队列。最大值队列中维护的是,当前队列中的最大值。

但是怎么维护呢?比如来了一个数字6.5。那么就应该变成:

                                

其实也不难。就是单调队列该了一下,如果当前元素i比队尾元素大,则队尾元素出栈,并计数。最后出去几个元素就进去几个i。

 

第一个队列使用普通的队列就行,第二个队列因为要从后面出元素,所以使用双端队列。

 

【代码】

 

//MyQueue.java

package cn.itcast.demo12;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

public class MyQueue {
    Queue<Integer> queue;
    Deque<Integer> deque;
    
    public MyQueue(){
        queue = new LinkedList<Integer>();
        deque = new LinkedList<Integer>();
    }
    
    public void push_back(int e){
        queue.offer(e);
        
        int num = 1;                                                                   //不出的时候,也要把自身进去
        while(!deque.isEmpty() && deque.peekLast()<e){
            deque.pollLast();
            num++;                                                                      //出的时候,统计一下
        }
        
        while(num!=0){
            deque.offerLast(e);
            num--;
        }
    }
    
    public int pop_front(){
        deque.pollFirst();
        return queue.poll();
    }
    
    public int max(){
        return deque.peekFirst();
    }
    
}

Test.java

package cn.itcast.demo12;

public class Test {
    public static void main(String[] args) {
        MyQueue mq = new MyQueue();
        
        mq.push_back(3);  //3
        mq.push_back(5);  // 3 5
        System.out.println(mq.max());  //5
        mq.push_back(4);  //3 5 4 
        System.out.println(mq.max());  //5
        mq.pop_front();   //5 4
        mq.pop_front();   //4
        System.out.println(mq.max());  //4
        mq.push_back(3); //4 3
        System.out.println(mq.max());  //4
        mq.pop_front(); //3
        System.out.println(mq.max());  //3
               
    }
}

结果:

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值