剑指--队列的最大值

剑指–队列的最大值

1,题目:

在这里插入图片描述
2,思路:

看下面的代码

3,代码:

写法一:(队列+两个栈):

class MaxQueue {

/*
    等下,我们使用一个队列正常的存放数据,
    然后使用维护一个单调栈,栈顶为最大值
    再加一个辅助栈

    元素插入顺序:1   3   5   5   2   6   1   2

    (栈的元素最左边为栈底,最右边为栈顶,队列也一样)
    插入 1:
    queue = {1}
    stack = {1}
    插入 3
    queue = {3, 1}
    stack = {3}
    (
        这里为什么 stack 是 3?之前的 1 哪去了?
        因为 1 比 3 先插入,因此最先 poll() 的必定会是 1,而在 poll 3 之前,无论 1 是否存在,最大值都会是 3,因此 1 的存在无关紧要
        这里我们就可以知道,只要后面进来一个比之前存储元素都要大的,那么前面的小元素都无关紧要了,清空栈,只入栈这个最大元素
    )
    插入 5
    queue = {5, 3, 1}
    stack = {5}
    插入 5
    queue = {5,5, 3, 1}
    stack = {5,5}
    (
        插入跟栈顶元素一样大的值,这个就不必多说什么了吧,直接入栈即可
    )
    插入 2
    queue = {2, 5, 5, 3, 1}
    stack = {2, 5, 5}
    (
        这里为什么 2 又存在了? 而且是在栈底?
        因为 5 比 2 先插入,因此最先 poll() 的一定会是 5,那么当 poll 5 的时候,前面的 1 和 3 也都已经 poll() 了
        那么队列剩下的就是 5 后面插入元素的最大值,即 2,因此我们需要留下 2
    )
    插入 6
    queue = {6, 2, 5, 5, 3, 1}
    stack = {6}
    插入 1
    queue = {1, 6, 2, 5, 5, 3, 1}
    stack = {1, 6}
    插入 2
    queue = {2, 1, 6, 2, 5, 5, 3, 1}
    stack = {2, 6}
    (
        这里为什么是 2 在底部? 1 哪去了?
        6 比 后面的 1 和 2 都先插入,因此在 poll 6 之前, 6 是最大的
        而 1 比 2 先插入,因此在 poll 2 之前,前面的 1 是否存在无关紧要,当 poll 6 后,最大值就会是 6 后面插入元素的最大值。即 2
        这里我们就知道,我们当插入元素比 栈顶元素 小的时候,我们需要清空掉 栈内所有比 插入元素小的值,然后入栈
        (这里做法就是 面试题 03.05. 栈排序 的做法)
    )
    */




    Queue<Integer> queue;//队列
    Deque<Integer> stack;//栈
    Deque<Integer> helper_stack;//辅助栈
    public MaxQueue() {
        queue = new LinkedList<>();
        stack = new LinkedList<>();
        helper_stack = new LinkedList<>();
    }
    
    public int max_value() {
        if(queue.isEmpty()){
            return -1;
        }
        return stack.peek();//返回最大值
    }
    
    public void push_back(int value) {
        queue.add(value);
        //栈为空,直接入栈
        if(stack.isEmpty()){
            stack.push(value);
        }else{
            if(stack.peek() < value){   //当栈顶元素比当前元素小,那么清空栈,然后将 value 入栈
                stack.clear();
                stack.push(value);
            }else if(stack.peek() == value){    //当栈顶元素等于当前元素,那么直接入栈
                stack.push(value);
            }else{
                while(!stack.isEmpty() && stack.peek() >= value){   //当栈顶元素大于当前元素,将大于等于 value 的值压入辅助栈
                    helper_stack.push(stack.pop());
                }
                //压入插入元素
                helper_stack.push(value);
                //清空 stack 
                stack.clear();
                //重新将辅助栈的值压回 stack
                while(!helper_stack.isEmpty()){
                    stack.push(helper_stack.pop());
                }
            }
        }
    }
    
    public int pop_front() {
        if(queue.isEmpty()){
            return -1;
        }
        int temp = queue.poll();
        if(stack.peek() == temp){
            stack.pop();
        }
        return temp;
    }
}

写法二:(队列+双端队列):

class MaxQueue {
    Queue<Integer> que;
    Deque<Integer> deq;

    public MaxQueue() {
        que = new LinkedList<>();  //队列:插入和删除
        deq = new LinkedList<>();  //双端队列:获取最大值
    }
    
    public int max_value() {
        return deq.size()>0?deq.peek():-1;  //双端队列的队首为que的最大值
    }
    
    public void push_back(int value) {
        que.offer(value);  //value入队
        while(deq.size()>0 && deq.peekLast()<value){
            deq.pollLast();  //将deq队尾小于value的元素删掉
        }
        deq.offerLast(value);  //将value放在deq队尾
    }
    
    public int pop_front() {
        int tmp = que.size()>0?que.poll():-1;  //获得队首元素
        if(deq.size()>0 && deq.peek().equals(tmp)){
            deq.poll();  //如果出队的元素是当前最大值,将deq的队首出队
        }
        return tmp;
    }
}


写法三:队列+双端链表:

public class MaxQueue {

    Queue<Integer> queue;
    LinkedList<Integer> max;
    public MaxQueue() {
        queue = new LinkedList<>();
        max = new LinkedList<>();//LinkedList是双端链表
    }
    
    public int max_value() {
        return max.size()==0?-1:max.getFirst();
    }
    
    public void push_back(int value) {
        queue.add(value);
        while(max.size()!=0&&max.getLast()<value){//注意:这里第二个判断条件不能带等号,即max中对于当前queue中的具有相同值的元素会全部存储,而不是存储最近的那个。
            max.removeLast();
        }
        max.add(value);
    }
    
    public int pop_front() {
        if(max.size()!=0&&queue.peek().equals(max.getFirst()))//Integer类型的值的比较不能直接使用==
            max.removeFirst();
        return queue.size()==0?-1:queue.poll();
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值