剑指 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), 当所有元素是按递减的顺序压入的时候