工作上一定没人这么搞,但这是考察对栈、队列理解程度的好题

题目

力扣题目链接

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(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(双端队列)来模拟一个栈,只要是标准的栈操作即可。

进阶:

  • 你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。

示例:

  1. 输入:
  2. ["MyQueue", "push", "push", "peek", "pop", "empty"]
  3. [[], [1], [2], [], [], []]
  4. 输出:
  5. [null, null, null, 1, 1, false]
  6. 解释:
  7. MyQueue myQueue = new MyQueue();
  8. myQueue.push(1); // queue is: [1]
  9. myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
  10. myQueue.peek(); // return 1
  11. myQueue.pop(); // return 1, queue is [2]
  12. myQueue.empty(); // return false

提示:

  • 1 <= x <= 9
  • 最多调用 100 次 push、pop、peek 和 empty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

思路

这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。

使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。

下面动画模拟以下队列的执行过程如下:

执行语句:
queue.push(1);
queue.push(2);
queue.pop(); 注意此时的输出栈的操作
queue.push(3);
queue.push(4);
queue.pop();
queue.pop();注意此时的输出栈的操作
queue.pop();
queue.empty();
232.用栈实现队列版本2.gif
在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。

在代码实现的时候,会发现 pop() 和 peek() 两个函数功能类似,代码实现上也是类似的,可以思考一下如何把代码抽象一下。

答案

Java

  1. class MyQueue {
  2. Stack<Integer> stack1; // 输入栈
  3. Stack<Integer> stack2; // 输出栈
  4. /**
  5. * Initialize your data structure here.
  6. */
  7. public MyQueue() {
  8. stack1 = new Stack<>(); // 负责进栈
  9. stack2 = new Stack<>(); // 负责出栈
  10. }
  11. /**
  12. * Push element x to the back of queue.
  13. */
  14. public void push(int x) {
  15. stack1.push(x);
  16. }
  17. /**
  18. * Removes the element from in front of queue and returns that element.
  19. */
  20. public int pop() {
  21. if (stack2.isEmpty()) {
  22. dumpStack1ToStack2();
  23. }
  24. return stack2.pop();
  25. }
  26. /**
  27. * Get the front element.
  28. */
  29. public int peek() {
  30. if (stack2.isEmpty()) {
  31. dumpStack1ToStack2();
  32. }
  33. return stack2.peek();
  34. }
  35. /**
  36. * Returns whether the queue is empty.
  37. */
  38. public boolean empty() {
  39. return stack1.isEmpty() && stack2.isEmpty();
  40. }
  41. // 将 stack1 中的元素全部放到stack2中
  42. private void dumpStack1ToStack2() {
  43. while (!stack1.isEmpty()) {
  44. stack2.push(stack1.pop());
  45. }
  46. }
  47. }

REF

https://leetcode-cn.com/problems/implement-queue-using-stacks/