Recorded on November 28, 2021
Next up was the last blog post on stacks and queues Stack and queue title record (I)
232. Implement queue with stack
Idea: this topic is a simulation problem to investigate the understanding of stack and queue.
Because the stack is Filo (can only enter and pop up at the top of the stack), and the queue is FIFO (leaving the queue at the head of the queue and entering the queue at the end of the queue), two stacks are needed to implement the queue with the stack: input stack stIn and output stack stOut.
(1) push operation of queue
Directly let the input stack do the stack operation.
(2) pop operation of queue
Judge whether the output stack is empty: if not, pop up the elements in the output stack directly; If it is empty, the elements in the input stack will be ejected and put into the output stack. At this time, the bottom element in the original input stack will become the top element in the output stack. Continue this operation until the input stack is empty, then all the elements in the input stack will be transported to the output stack. At this time, ejecting the elements in the output stack will be the out of queue elements of the queue.
(3) peek operation of queue
The same idea as pop
Judge whether the output stack is empty: if it is not empty, the top element of the output stack is the result; If it is empty, all the elements in the input stack are transported to the output stack. At this time, the elements at the bottom of the original input stack become the top of the stack, and then the top of the stack is the result.
(4) empty operation of queue
When the input stack and output stack are empty, the queue is empty.
class MyQueue { Stack<Integer> stIn; Stack<Integer> stOut; public MyQueue() { stIn = new Stack<>(); stOut = new Stack<>(); } public void push(int x) { stIn.push(x); } public int pop() { if(stOut.empty()){ while(!stIn.empty()){ stOut.push(stIn.pop()); } } return stOut.pop(); } public int peek() { if(stOut.empty()){ while(!stIn.empty()){ stOut.push(stIn.pop()); } } return stOut.peek(); } public boolean empty() { return stIn.empty() && stOut.empty(); } } /** * Your MyQueue object will be instantiated and called as such: * MyQueue obj = new MyQueue(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.peek(); * boolean param_4 = obj.empty(); */
Thinking: because the queue is first in first out, and the stack is first in and then out, the first in elements will be placed at the bottom of the stack. If you want to get them out of the queue, you need an intermediary to change the original ones at the bottom of the stack to the top of the stack, and then it will be correct when they are out of the queue.
225. Implement stack with queue
1.1 solution 1: single queue implementation
Idea: since the stack is first in and then out, and the queue is first in and first out, when using a queue to implement the stack, it is necessary to ensure that the elements at the front end of the queue are the last elements in the stack.
(1) push operation of stack
If no processing is done, the order of storing elements in the queue and the order of storing elements in the stack should be exactly the opposite, that is, the elements at the bottom of the stack correspond to the front end of the queue, and the elements at the top of the stack correspond to the tail of the queue.
During stacking operation, first obtain the number n of elements in the queue at this time, then queue the element to the queue, and then queue out and queue in turn the n elements at the front of the queue (except all other elements of new stacked elements). At this time, the elements at the front of the queue are new stacked elements, and the storage order in the queue is the same as that in the stack, That is, the elements at the bottom of the stack correspond to the tail of the queue, and the elements at the top of the stack correspond to the head of the queue.
It is similar to imagining a queue as a ring, and transferring the front elements to the back through the ring.
(2) pop operation of stack
Since the order of queue and stack is the same, you can directly get the queue out of the queue.
(3) top operation of stack
Since the queue and stack are in the same order, the front-end elements of the queue are returned directly.
(4) empty operation of stack
Just judge whether the queue is empty.
class MyStack { Queue<Integer> que; public MyStack() { que = new LinkedList<>(); } public void push(int x) { int n = que.size(); que.offer(x); for(int i = 0;i < n;i++){ que.offer(que.poll()); } } public int pop() { return que.poll(); } public int top() { return que.peek(); } public boolean empty() { return que.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(); */
Thinking: use the queue to implement the stack. Each time you enter the stack, the element at the top of the stack is placed at the back of the queue. Therefore, if you queue all the elements in front of the element in the queue, you will put the element at the front of the queue. It is equivalent to treating the queue as a ring and linking the front elements to the back through the ring.
1.2 solution 2: two queue implementation
Idea: define two queues, where que1 represents the queue in the same order as the elements in the stack, and que2 represents the auxiliary queue.
When entering the stack, first queue the elements to que2, and then queue all the elements in que1 out of the queue and into que2 in turn. At this time, the front-end elements in que2 are the newly stacked elements. Then swap que1 and que2, the elements in que1 are the elements in the stack, and the front-end and back-end of the queue correspond to the top and bottom of the stack respectively.
In fact, que2 is always empty. Its purpose is to put in a new element, and then put the element of que1 into the que2 queue, so that the later stacked element is at the front, and then exchange que1 and que2. At this time, que2 is empty again.
class MyStack { Queue<Integer> que1; Queue<Integer> que2; public MyStack() { que1 = new LinkedList<>(); que2 = new LinkedList<>(); } public void push(int x) { que2.offer(x); while(!que1.isEmpty()){ que2.offer(que1.poll()); } Queue<Integer> tmp = new LinkedList<>(); tmp = que1; que1 = que2; que2 = tmp; } public int pop() { return que1.poll(); } public int top() { return que1.peek(); } public boolean empty() { return que1.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(); */
Thinking: two queues are used to realize the stack. In fact, the first queue always stores the elements in the same order as the elements in the stack. At first, the second queue is used to store the new elements in the stack, and then the elements in the first queue are entered into the second queue. At this time, the elements in the second queue are obviously stored in the same order as those in the stack, and then the two queues are exchanged. This ensures that the newly stacked element is at the top of the queue.