用栈实现队列
对应力扣232.用栈实现队列
题目:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例:
输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
做题思路
做这个题的时候首先要明确,栈的特点是:先进后出(均在尾端操作)。队列的特点是:先进先出(尾进首出)。所以很容易就想到要用到两个栈去模拟队列,我们可以把一个定义为输入栈,另一个定义为输出栈。队列的添加操作直接把数据装入输入栈即可,而pop(),peak()操作则跟输出栈有关。每当要输出的时候先判断输出栈是否为空,如果为空就把输入栈的数据全部弹过来(如果只弹一个过去有可能删的就不是队列的头元素了,也就是说只要从输入栈弹东西到输出栈里面去,都要整体弹出来,来保持顺序。),如果不为空就直接吧输出栈的弹出就行了。
empty()的实现通过两个栈总情况而定,如果均为空则返回true,如果有一个不为空就返回false。
代码实现
Stack<Integer> box1; //输入栈
Stack<Integer> box2; //输出栈;
public MyQueue2() {
box1 = new Stack<>();
box2 = new Stack<>();
}
public void push(int x) {
box1.push(x);
}
public int pop() {
tanChu();
return box2.pop();
}
public int peek() {
tanChu();
return box2.peek();
}
public boolean empty() {
return box1.empty() && box2.empty();
}
public void tanChu(){
if(box2.empty()){
while(!box1.empty()){
box2.push(box1.pop());
}
}
}
用队列实现栈
对应力扣的225.用队列实现栈
题目:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]
解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
做题思路
用队列去实现栈的话存在两种方式
- 双队列模拟
- 单队列模拟
方式一思路
先定义两个队列A,B。push()操作做均是往队列A中加。而top(),pop()操作我们的思路就是把A中的元素弹到B中,直到A中只剩下要删除的那最后一个元素即可。同时要注意只要把B中元素拿到A中去一定是整体拿,否则添加会影响顺序。此方法的宗旨就是:pop(),top()操作时,A中永远只有一个元素,如果两个或者多个,多出来的往B弹;如果A中没有元素,把B全部弹到A,再继续上述操作。
方式二思路
定义一个队列A,实现pop(),top()操作只需要通过队列的弹出,再加入,使要删除的元素成为头部元素即可。
注意点:
- 我们在控制弹出个数的时候,前面都是直接用的size(),但是这里不行,因为这里弹出之后会立刻被添加,是一个循环的过程,故我们引入计数器,来控制我们的弹出操作,使要删除的尾元素称为头元素。
- 在top()的实现中前半部分的思路与pop()相同。但当你返回了队头元素之后没有弹出,所以不能就不管了,否则此时添加的话会打乱顺序,故我们返回了之后要把队列还原(也就是把队头元素弹出去再添加,恢复原始顺序)
方式一代码实现
public class MyStack {
Queue<Integer> box1;
Queue<Integer> box2;
public MyStack() {
box1 = new LinkedList<>();
box2 = new LinkedList<>();
}
public void push(int x) {
box1.add(x);
}
public int pop() {
shuSong();
return box1.remove();
}
public int top() {
shuSong();
return box1.peek();
}
public boolean empty() {
return box1.isEmpty() && box2.isEmpty();
}
public void shuSong(){
if(box1.isEmpty()){
while(!box2.isEmpty()){
box1.add(box2.remove());
}
}
while(box1.size() != 1){
box2.add(box1.remove());
}
}
}
方式二代码实现
public class MyStack2 {
// 此法用一个队列实现栈结构
Queue<Integer> box;
public MyStack2() {
box = new LinkedList<>();
}
public void push(int x) {
box.add(x);
}
public int pop() {
reList();
return box.remove();
}
public int top() {
reList();
int ans = box.peek();
box.add(box.remove());
return ans;
}
public boolean empty() {
return box.isEmpty();
}
public void reList(){
int flag = box.size();
while(flag != 1){
box.add(box.remove());
flag--;
}
}
}
做题反思
在使用栈模拟队列的时候,一开始我的代码效率不高:
public class MyQueue {
Stack<Integer> box1 = new Stack<>();
Stack<Integer> box2 = new Stack<>();
public MyQueue() {
}
public void push(int x) {
while(!box2.empty()){
box1.push(box2.pop());
}
box1.push(x);
}
public int pop() {
zhuRu();
return box2.pop();
}
public int peek() {
zhuRu();
return box2.peek();
}
public boolean empty() {
return box1.empty() && box2.empty();
}
public void zhuRu(){
while(!box1.empty()){
box2.push(box1.pop());
}
}
}
当是想的为了保证顺序,每当添加的时候,都要把输出栈的元素重新弹回到输入栈再添加,其实不用。直接在输入栈中添加,当输出栈为空时再把输入栈全部弹到输出栈,同样也可以保持顺序。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122333.html