JAVA程序设计:队列的最大值(LeetCode:面试题59)

请定义一个队列并实现函数 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

思路:本题限制要求所有操作必须在O(1)的复杂度完成,因此很多方法会被pass掉,思考了良久,到底怎样才能保证O(1)去更新队列里的最大值呢,进一步分析我们应该如何使得每次弹出的值不会影响最大值呢?

我们应思考本题中隐藏的一个性质:当一个元素进入队列的时候,它前面所有比它小的元素就不会再对答案产生影响。

举个例子,如果我们向队列中插入数字序列 1 1 1 1 2,那么在第一个数字 2 被插入后,数字 2 前面的所有数字 1 将不会对结果产生影响。因为按照队列的取出顺序,数字 2 只能在所有的数字 1 被取出之后才能被取出,因此如果数字 1 如果在队列中,那么数字 2 必然也在队列中,使得数字 1 对结果没有影响。

按照上面的思路,我们可以设计这样的方法:从队列尾部插入元素时,我们可以提前取出队列中所有比这个元素小的元素,使得队列中只保留对结果有影响的数字。这样的方法等价于要求维持队列单调递减,即要保证每个元素的前面都没有比它小的元素。

我们可以采用队列+双端队列的组合进行实现,其中队列完成正常的入队和出队,而双端队列用来维护以上上述所说的递减队列。其实经分析感觉每次并不是O(1)的,因为存在while循环,看了一些人的讲解说其均摊复杂度为O(1),好吧~~~

class MaxQueue {
	
	Queue q1;
	Deque q2;
	
    public MaxQueue() {
    	q1=new LinkedList<>();
    	q2=new LinkedList<>();
    }
    
    public int max_value() {
    	if(q2.isEmpty())
    		return -1;
    	return q2.getFirst();
    }
    
    public void push_back(int value) {
    	while(!q2.isEmpty() && q2.getLast()

 

你可能感兴趣的:(JAVA程序设计:队列的最大值(LeetCode:面试题59))