leetcode 剑指 Offer 59 - II. 队列的最大值

剑指 Offer 59 - II. 队列的最大值

题目描述

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

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

示例 1:

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

示例 2:

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

限制:

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

思路:

借助一个双端队列,这个双端队列中存储了每个元素对应的最大值,入队一个比较大的元素后,队列中所有比他小的元素的最大值都应该更新为它,所以应该出队双端队列尾部所有小于该元素的值。详情请参考:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/ru-he-jie-jue-o1-fu-za-du-de-api-she-ji-ti-by-z1m/

 1 class MaxQueue {
 2 
 3     // 两个队列,一个队列用来实际存数据,另一双端队列用来存最大值
 4     Queue<Integer> queue1;
 5     Deque<Integer> queue2;
 6     public MaxQueue() {
 7         queue1 = new LinkedList<Integer>();
 8         queue2 = new LinkedList<Integer>();
 9     }
10     
11     public int max_value() {
12         if(queue2.isEmpty()){
13             return -1;
14         }
15         return queue2.peekFirst();
16     }
17     
18     public void push_back(int value) {
19         // queue2的队尾元素小于value时,一直弹出该队尾元素
20         while(!queue2.isEmpty() && queue2.peekLast() < value){
21             queue2.pollLast();
22         }
23         // 随后把value压入两个队列中
24         queue1.offer(value);
25         queue2.offerLast(value);
26     }
27     
28     public int pop_front() {
29         // 两个队列同时pop
30         if(queue1.isEmpty()){
31             return -1;
32         }
33         // 如果queue1的队首元素等于queue2的队首元素,同时出队,否则只需要出队queue1
34         if(queue1.peek() == queue2.peekFirst()){
35             queue2.pollFirst();
36         }
37         return queue1.poll();
38     }
39 }

上面的代码我看着没错,但是就是通过不了所有的测试用例,测试用例太长了,不想看

复杂度分析:

时间复杂度:max_value()和pop_front()都是O(1), push_back()每个最大值元素只会被入队和出队一次,所以平均时间复杂度也为O(1)

空间复杂度:借助了一个双端队列,队列最大为O(n), 当所有元素是按递减的顺序压入的时候

 

posted @ 2020-10-02 20:51  Lucky小黄人^_^  阅读(126)  评论(0编辑  收藏  举报