请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
方法一:两个队列
两个队列,入队都入q1,每次pop/peek除了最后一个都移入另一个队列,区别在于peek完还要重新入队
class MyStack {
Queue<Integer>q1;
Queue<Integer>q2;
public int size;
public MyStack() {
q1=new LinkedList<>();
q2=new LinkedList<>();
size=0;
}
public void push(int x) {
q1.offer(x);
size++;
}
public int pop() {
size--;
if(q1.size()==0){
while(q2.size()>1){
q1.offer(q2.poll());
}
return q2.poll();
}
while(q1.size()>1){
q2.offer(q1.poll());
}
return q1.poll();
}
public int top() {
if(q1.size()==0){
while(q2.size()>1){
q1.offer(q2.poll());
}
return q2.peek();
}
while(q1.size()>1){
q2.offer(q1.poll());
}
int res=q1.peek();
q2.offer(q1.poll());
return res;
}
public boolean empty() {
return size==0;
}
}
方法二:一个队列
很简单,就是记录栈的大小,入栈就直接offer即可,pop的时候要的是最后入队的元素,总共有n个元素,我们将n-1个元素出队再入队,那么原先最后入队的元素此时就在队尾,如果pop就直接poll,如果peek就peek完将其重新入队,保持原结构不变。
class MyStack {
Queue<Integer>q;
public int size;
public MyStack() {
q=new LinkedList<>();
size=0;
}
public void push(int x) {
q.offer(x);
size++;
}
public int pop() {
size--;
for(int i=0;i<size;i++){
q.offer(q.poll());
}
return q.poll();
}
public int top() {
for(int i=0;i<size-1;i++){
q.offer(q.poll());
}
int top=q.peek();
q.offer(q.poll());
return top;
}
public boolean empty() {
return size==0;
}
}
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
这个题目和225不同,区别在于队列有两个口,可以一进一出,一个队列可以同时实现进出功能,但是栈只有一个口,一个栈无论如何是无法实现双口队列的,所以必须要用两个栈来实现
方法一:用两个栈,一个用来输入数据,一个用来输出数据,我们可以认为,队列的先进先出输出模式符合人类的正常思维,所以栈实际上是一次倒序输出,而两次倒序,自然就是正序输出了,正向输入instack,再输出到outstack,最后输出outstack即可
class MyQueue {
Stack<Integer> inStack;
Stack<Integer> outStack;
int size;
public MyQueue() {
inStack = new Stack<Integer>();
outStack = new Stack<Integer>();
size=0;
}
public void push(int x) {
size++;
inStack.push(x);
}
public int pop() {
for(int i=0;i<size;i++){
outStack.push(inStack.pop());
}
int res=outStack.pop();
size--;
for(int i=0;i<size;i++){
inStack.push(outStack.pop());
}
return res;
}
public int peek() {
for(int i=0;i<size;i++){
outStack.push(inStack.pop());
}
int res=outStack.peek();
for(int i=0;i<size;i++){
inStack.push(outStack.pop());
}
return res;
}
public boolean empty() {
return size==0;
}
}
优化:我们实际上不需要倒来倒去,oustack装的就是符合队列性质的数据,直接用来输出即可,等没法再输出了,再把instack的数据装入outstack中即可
class MyQueue {
Stack<Integer> inStack;
Stack<Integer> outStack;
int size;
public MyQueue() {
inStack = new Stack<Integer>();
outStack = new Stack<Integer>();
size=0;
}
public void push(int x) {
size++;
inStack.push(x);
}
public int pop() {
//我们不必每次都倒来倒去,队列先进先出,
//所以我们一次性装进outstack之后,outstack内的数据就符合队列了
//直到outstack空了,才需要加入新数据
if(outStack.isEmpty()){
for(int i=0;i<size;i++){
outStack.push(inStack.pop());
}
}
size--;
return outStack.pop();
}
public int peek() {
if(outStack.isEmpty()){
for(int i=0;i<size;i++){
outStack.push(inStack.pop());
}
}
return outStack.peek();
}
public boolean empty() {
return size==0;
}
}