队列的最大值

题目描述

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_valuepush_backpop_front均摊时间复杂度都是$O(1)$。
若队列为空,pop_frontmax_value 需要返回 -1。
示例 1:

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

示例 2:

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

限制:

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

题目链接

Leetcode

题目解答

解法一

使用数组记录插入队列的值,遍历队列所有元素求最大值,这种处理方式能够得到正确结果,但是不能完全满足题目要求。

时间复杂度:$O(1)$(插入、删除),$O(n)$(求最大值) 空间复杂度:$O(n)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MaxQueue {

int[] queue;
int head = 0, tail = 0;

public MaxQueue() {
queue = new int[20000];
}

public int max_value() {
int max = -1;
for (int i = head; i != tail; i++) {
max = Math.max(queue[i], max);
}
return max;
}

public void push_back(int value) {
queue[tail++] = value;
}

public int pop_front() {
if (head == tail) return -1;
return queue[head++];
}
}

/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue obj = new MaxQueue();
* int param_1 = obj.max_value();
* obj.push_back(value);
* int param_3 = obj.pop_front();
*/

执行用时:38 ms, 在所有 Java 提交中击败了96.06%的用户
内存消耗:43.6 MB, 在所有 Java 提交中击败了98.47%的用户

解法二

定义队列queue进行元素的插入和删除,定义双端队列order用于维护队列中的最大值。对于插入操作,需要比较插入值和order队尾值的大小,如果队尾值较小就把队尾元素删除,重复这一过程,直至队尾元素为空或者插入值比队尾元素小,此时就可以把插入值同时插入队列queueorder。对于删除操作,需要比较两个队列队首元素是否相同,如果相同就把两个队列的队首元素都删除,如果不相同只删除queue队首元素。对于求最大值操作每次返回order队首元素值即可。对于order中的每个元素来说,入队和出队都只有1次,所以可以保证整体插入操作的均摊时间复杂度为$O(1)$。

时间复杂度:$O(1)$ 空间复杂度:$O(n)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class MaxQueue {
LinkedList<Integer> queue;
LinkedList<Integer> order;

public MaxQueue() {
queue = new LinkedList<>();
order = new LinkedList<>();
}

public int max_value() {
return order.isEmpty() ? -1 : order.peek();
}

public void push_back(int value) {
while (!order.isEmpty() && order.peekLast() < value) {
order.pollLast();
}
queue.add(value);
order.addLast(value);
}

public int pop_front() {
if (queue.isEmpty()) return -1;
int front = queue.pop();
if (front == order.peek()) {
order.pop();
}
return front;
}
}

执行用时:38 ms, 在所有 Java 提交中击败了96.06%的用户
内存消耗:46.4 MB, 在所有 Java 提交中击败了36.11%的用户

-------------本文结束 感谢您的阅读-------------

文章对您有帮助,可以打赏一杯咖啡,鼓励我继续创作!