1.用两个栈来实现一个队列
要求: 完成队列的Push和Pop操作。( 队列中的元素为int类型)
对于这个问题,《剑指offer》上有一张图很形象:
在图中可以看出它用stack1来模拟入队列,用stack2来模拟出队列。然后注意两点就可以很容易的完成这个问题:
- 1.push( )操作,直接将数据压入stack1即可;
- 2.pop( )操作,将stack1中的数据弹出然后再压入到stack2中,这样数据在两个栈中顺序就相反了,这样就保证了stack2()栈顶元素一直是最先进队列的元素,为保证最先进入的数据一直处于栈顶,只有将stack2中的数据全部pop后,才能继续讲stack1中的数据压入到stack2中,继续做pop()。
代码:
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node); //入队列,直接将数据压入stack1()中
}
public int pop() {
if(stack2.empty()) { //stack2栈顶一直是最先进入队列的元素,为保证出队列时它能第一个出,所以它只要不为空,stack1中的元素就得老实待着,不能弹出到stack2中。
while(!stack1.empty()) { //stack2空了之后,stack1栈底元素就成了最先进入队列的元素,此时就可以将stack1中的数据全部弹出到stack2中。这样stack2的栈顶元素又是最先进入队列的元素了。
stack2.push(stack1.pop());
}
}
return stack2.pop(); //由于有了上面前提,stack2栈顶元素,一直都是最先进入队列的元素。
}
}
2.用两个队列来实现一个栈
题目链接:LeetCode 225
要求实现以下功能:
- push(x) – 元素 x 入栈
- pop() – 移除栈顶元素
- top() – 获取栈顶元素
- empty() – 返回栈是否为空
做法:
- 入栈:类似于上面用栈实现队列,这里直接把数据入q1;
- 出栈:模拟出栈操作大概可以分三步:
第一步:将q1中的元素留一个,剩下的全部出队,进入q2。 留一个是因为,出栈顺序是先入后出,先把它之前的所有元素搬走,再将它出队列,就完成了出栈操作;
第二步:将q1中剩下的最后一个元素出队列,就完了出栈操作。 (因为他就是最后一个进入栈的元素);
第三步:交换q1,q2。 前面已经可以完成出栈操作,为什么还会有这个第三步呢?因为为了省事,如果不交换,每次都要再出栈都要判断两个队列哪个不为空。很麻烦。
代码:
class MyStack {
private Queue<Integer> q1;
private Queue<Integer> q2;
/** Initialize your data structure here. */
public MyStack() {
q1 = new LinkedList<>();
q2 = new LinkedList<>(); //在构造函数里给两个队列初始化
}
/** Push element x onto stack. */
public void push(int x) {
q1.offer(x); //入栈就直接把元素放进q1
}
/** Removes the element on top of the stack and returns that element. */
//模拟出栈操作大概可以分三步:
//第一步:将q1中的元素留一个,剩下的全部出队,进入q2。 留一个是因为,出栈顺序是先入后出,先把它之前的所有元素搬走,再将它出队列,就完成了出栈操作。
//第二步:将q1中剩下的最后一个元素出队列,就完了出栈操作。 (因为他就是最后一个进入栈的元素)
//第三步:交换q1,q2。 前面已经可以完成出栈操作,为什么还会有这个第三步呢?因为为了省事,如果不交换,每次都要再出栈都要判断两个队列哪个不为空。很麻烦。
public int pop() {
while(q1.size()>1) { //第一步:q1队尾留下,剩下的全部进入q2
q2.offer(q1.poll());
}
int ret = q1.poll(); //第二步:将刚刚那个留下的队尾元素出队。
Queue<Integer> temp = q1;
q1 = q2;
q2 = temp; //第三步:交换q1,q2
return ret;
}
/** Get the top element. */
//获取栈顶元素
public int top() {
//第一步将q1中size-1个元素搬移到q2中
while(q1.size()>1) {
q2.offer(q1.poll());
}
//获取q1队头元素
int ret = q1.peek();
//将其搬运到q2
q2.offer(q1.poll());
//第三步交换q1,q2,不交换的话话在插的时候就需要考虑哪个队列不为空插哪个很麻烦,直接暴力一点,交换省事。
Queue<Integer> temp = q1;
q1 = q2;
q2 = temp;
return ret;
}
/** Returns whether the stack is empty. */
public boolean empty() {
return q1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/