问题描述:
实现一个队列,使得它的push_rear(), pop_front() 和get_min() 这三个函数的时间复杂的为常数(即O(1))。
分析:
在leetcode上面有类似的题目,但是其所要求的是实现一个栈(stack)而不是队列。
这里将使用两个栈来作为辅助数据结构。第一个栈专门用来接收新来的数据,第二个栈专门接收第一个栈中的数据。每一次都把第一个栈中的所有数据倒转到第二个中。数据永远从第二个栈中pop出去。
具体举例来看:现在四个数字[1, 5, 2, 4] (4是最早到达的数据)依次压入栈中,每压入一个数字的时候,在其旁边(黄色背景)使用另一个数字记录当前栈中最小的值。所以,从下图中,当压入数字5的时候,当前栈中最小的值是2,所以其旁边的数字为2.
四个数字入栈之后,把它们分别弹出然后再次入栈到第二个栈中。黄色背景的数值依然是记录当前栈中最小的数字。当需要pop front操作的时候,把第二个栈中top元素弹出。
这时候发现,这三个函数push_rear(), pop_front() 和get_min()的时间复杂度是为O(0)的。算法运行期间间歇性的将数据从栈1中倒转到栈2中,这个操作所用的时间复杂度为O(n),但是因为并不是在操作每一个元素的时候都需要倒转,所以平均下来整个算法的三个函数的时间复杂度是常数。
实现
import java.util.EmptyStackException;
import java.util.Stack;
public class ContantQueue {
private Stack<Value> s1 = new Stack<>();
private Stack<Value> s2 = new Stack<>();
public void pushRear(int value){
System.out.println("input number: "+value);
pushRear(s1, value);
}
private void pushRear(Stack<Value> s, int value){
if(s.empty())
s.push(new Value(value, value));
else{
if(value > s.peek().min){
s.push(new Value(value, s.peek().min));
}else{
s.push(new Value(value, value));
}
}
}
public int popFront(){
if(empty()) throw new EmptyStackException();
return s2.pop().value;
}
public int getMin(){
if(empty()) throw new EmptyStackException();
return s2.peek().min;
}
public boolean empty(){
if(s2.empty()){
transferNums();
}
if(s2.empty()) return true;
else return false;
}
private void transferNums(){
if(s1.empty()) return;
while(!s1.empty()){
pushRear(s2, s1.pop().value);
}
}
class Value{
int value;
int min;
public Value(){}
public Value(int value, int min){
this.value = value;
this.min = min;
}
}
public static void main(String[] args) {
ContantQueue queue = new ContantQueue();
queue.pushRear(4);
queue.pushRear(2);
queue.pushRear(5);
queue.pushRear(1);
assert queue.popFront() == 4;
assert queue.popFront() == 2;
assert queue.popFront() == 5;
assert queue.popFront() == 1;
queue.pushRear(6);
queue.pushRear(2);
queue.pushRear(9);
queue.pushRear(7);
assert queue.popFront() == 6;
assert queue.getMin() == 2;
assert queue.popFront() == 2;
assert queue.getMin() == 7;
queue.pushRear(16);
queue.pushRear(8);
assert queue.popFront() == 9;
assert queue.popFront() == 7;
assert queue.popFront() == 16;
assert queue.popFront() == 8;
}
}
该代码实现只适用于单线程。
结束!