本节内容
理论基础
232.用栈实现队列
225. 用队列实现栈
理论基础※ 了解一下 栈与队列的内部实现机智,文中是以C++为例讲解的。
文章讲解:https://programmercarl.com/%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
https://www.yuanql.top/2023/07/03/02_leetcode/%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80/
232.用栈实现队列※ 建议 :大家可以先看视频,了解一下模拟的过程,然后写代码会轻松很多。
题目链接: https://leetcode.cn/problems/implement-queue-using-stacks/ 文章讲解: https://programmercarl.com/0232.%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.html
https://www.yuanql.top/2023/07/03/02_leetcode/232.%20%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97/
题目分析
方案一 曾经做过,有相关的印象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class MyQueue { private Deque<Integer> leftDeque; private Deque<Integer> rigthDeque; public MyQueue () { leftDeque = new LinkedList <>(); rigthDeque = new LinkedList <>(); } public void push (int x) { rigthDeque.push(x); } public int pop () { if (leftDeque.isEmpty()) { while (!rigthDeque.isEmpty()) { leftDeque.push(rigthDeque.pop()); } } return leftDeque.pop(); } public int peek () { if (leftDeque.isEmpty()) { while (!rigthDeque.isEmpty()) { leftDeque.push(rigthDeque.pop()); } } return leftDeque.peek(); } public boolean empty () { return leftDeque.isEmpty() && rigthDeque.isEmpty(); } }
结果 解答成功: 执行耗时:0 ms,击败了100.00% 的Java用户 内存消耗:39.2 MB,击败了83.29% 的Java用户
代码随想录 https://programmercarl.com/0232.%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.html
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈 ,这里要注意输入栈和输出栈的关系。
下面动画模拟以下队列的执行过程:
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class MyQueue { Stack<Integer> stackIn; Stack<Integer> stackOut; public MyQueue () { stackIn = new Stack <>(); stackOut = new Stack <>(); } public void push (int x) { stackIn.push(x); } public int pop () { dumpstackIn(); return stackOut.pop(); } public int peek () { dumpstackIn(); return stackOut.peek(); } public boolean empty () { return stackIn.isEmpty() && stackOut.isEmpty(); } private void dumpstackIn () { if (!stackOut.isEmpty()) return ; while (!stackIn.isEmpty()){ stackOut.push(stackIn.pop()); } } }
225. 用队列实现栈※ 建议 :可以大家惯性思维,以为还要两个队列来模拟栈,其实只用一个队列就可以模拟栈了。
建议大家掌握一个队列的方法,更简单一些,可以先看视频讲解
题目链接: https://leetcode.cn/problems/implement-stack-using-queues/ 文章讲解: https://programmercarl.com/0225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.html
https://www.yuanql.top/2023/07/04/02_leetcode/225.%20%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88/
题目分析
方案一 曾经做过,有相关的印象
仅仅使用了一个队列实现的,但是感觉时间复杂度有点高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class MyStack { private Deque<Integer> deque; private int length = 0 ; public MyStack () { deque = new LinkedList <>(); } public void push (int x) { deque.offer(x); for (int i = 0 ; i < length; i++) { deque.offer(deque.poll()); } length++; } public int pop () { length--; return deque.poll(); } public int top () { return deque.peek(); } public boolean empty () { return length == 0 ; } }
结果 解答成功: 执行耗时:0 ms,击败了100.00% 的Java用户 内存消耗:39.4 MB,击败了38.71% 的Java用户
代码随想录 https://programmercarl.com/0225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.html
队列模拟栈,其实一个队列就够了 ,那么我们先说一说两个队列来实现栈的思路。
队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。
所以用栈实现队列, 和用队列实现栈的思路还是不一样的,这取决于这两个数据结构的性质。
但是依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用来备份的!
如下面动画所示,用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用 ,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。
模拟的队列执行语句如下:
1 2 3 4 5 6 7 8 9 queue.push(1 ); queue.push(2 ); queue.pop(); queue.push(3 ); queue.push(4 ); queue.pop(); queue.pop(); queue.pop(); queue.empty();
优化 一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
代码实现 使用两个 Queue 实现方法1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class MyStack { Queue<Integer> queue1; Queue<Integer> queue2; public MyStack () { queue1 = new LinkedList <>(); queue2 = new LinkedList <>(); } public void push (int x) { queue2.offer(x); while (!queue1.isEmpty()){ queue2.offer(queue1.poll()); } Queue<Integer> queueTemp; queueTemp = queue1; queue1 = queue2; queue2 = queueTemp; } public int pop () { return queue1.poll(); } public int top () { return queue1.peek(); } public boolean empty () { return queue1.isEmpty(); } }
使用两个 Queue 实现方法2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class MyStack { Queue<Integer> q1 = new ArrayDeque <>(); Queue<Integer> q2 = new ArrayDeque <>(); public MyStack () { } public void push (int x) { while (q1.size() > 0 ) { q2.add(q1.poll()); } q1.add(x); while (q2.size() > 0 ) { q1.add(q2.poll()); } } public int pop () { return q1.poll(); } public int top () { return q1.peek(); } public boolean empty () { return q1.isEmpty(); } }
使用两个 Deque 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class MyStack { Deque<Integer> que1; Deque<Integer> que2; public MyStack () { que1 = new ArrayDeque <>(); que2 = new ArrayDeque <>(); } public void push (int x) { que1.addLast(x); } public int pop () { int size = que1.size(); size--; while (size-- > 0 ) { que2.addLast(que1.peekFirst()); que1.pollFirst(); } int res = que1.pollFirst(); que1 = que2; que2 = new ArrayDeque <>(); return res; } public int top () { return que1.peekLast(); } public boolean empty () { return que1.isEmpty(); } }
优化,使用一个 Deque 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class MyStack { Deque<Integer> que1; public MyStack () { que1 = new ArrayDeque <>(); } public void push (int x) { que1.addLast(x); } public int pop () { int size = que1.size(); size--; while (size-- > 0 ) { que1.addLast(que1.peekFirst()); que1.pollFirst(); } int res = que1.pollFirst(); return res; } public int top () { return que1.peekLast(); } public boolean empty () { return que1.isEmpty(); } }
优化,使用一个 Queue 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class MyStack { Queue<Integer> queue; public MyStack () { queue = new LinkedList <>(); } public void push (int x) { queue.offer(x); int size = queue.size(); while (size-- > 1 ) queue.offer(queue.poll()); } public int pop () { return queue.poll(); } public int top () { return queue.peek(); } public boolean empty () { return queue.isEmpty(); } }
优化,使用一个 Queue 实现,但用卡哥的逻辑实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class MyStack { Queue<Integer> queue; public MyStack () { queue = new LinkedList <>(); } public void push (int x) { queue.add(x); } public int pop () { rePosition(); return queue.poll(); } public int top () { rePosition(); int result = queue.poll(); queue.add(result); return result; } public boolean empty () { return queue.isEmpty(); } public void rePosition () { int size = queue.size(); size--; while (size-->0 ) queue.add(queue.poll()); } }