2

图解「剑指Offer」之使用栈实现队列

 2 years ago
source link: https://www.cxyxiaowu.com/444.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

图解「剑指Offer」之使用栈实现队列

剑指offer 2年前 0 3.6K

点击蓝色“五分钟学算法”关注我哟

加个“星标”,天天中午 12:15,一起学算法

图解「剑指Offer」之使用栈实现队列

作者 | 程序员小吴

来源 | 五分钟学算法

使用栈实现队列的下列操作:

  • push(x) — 将一个元素放入队列的尾部。
  • pop() — 从队列首部移除元素。
  • peek() — 返回队列首部的元素。
  • empty() — 返回队列是否为空。

示例:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);  
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

说明:

  • 你只能使用标准的栈操作 — 也就是只有 push to toppeek/pop from topsize 和  is empty  操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

这是一道很典型的为初级算法爱好者准备的算法题,首先简单介绍一下 队列 这两种数据结构。

队列

队列是一种 先进先出(first in – first out, FIFO)的数据结构,队列中的元素都从后端(rear)入队(push),从前端(front)出队(pop)。

栈是一种 后进先出(last in – first out, LIFO)的数据结构,栈中元素从栈顶(top)压入(push),也从栈顶弹出(pop)。


为了满足队列的 FIFO 的特性,我们需要用到两个栈,用它们其中一个来进行入队操作,用另一个来进行出队操作。

//@author:程序员小吴
class MyQueue {

    private Stack<Integer> in = new Stack<>(), out = new Stack<>();

    //定义一个辅助函数来处理当 out 为空时,将 in 里面的数据挪到 out 中去
    private void transferIfEmpty() {
         if (out.empty()){
             while (!in.empty()){
                   out.push(in.pop());
             }
         }
    }

    /** Initialize your data structure here. */
    public MyQueue() {

    }

    /** Push element x to the back of queue. */
    public void push(int x) {
        in.push(x);
    }

    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
      transferIfEmpty();
      return out.pop();
    }

    /** Get the front element. */
    public int peek() {
      transferIfEmpty();
      return out.peek();
    }

    /** Returns whether the queue is empty. */
    public boolean empty() {
      return in.empty() && out.empty();
    }
}

复杂度分析

代码实现中涉及到多个函数,每个函数的复杂度是有所区别的。

push操作

  • 时间复杂度:O(n) 。通过动画可知,除了新元素之外的其它元素,它们都会被压入两次,弹出两次。新元素只被压入一次,弹出一次。这个过程产生了 4n + 2 次操作,其中 n 是队列的大小。由于 压入 操作和 弹出 操作的时间复杂度为 O(1), 因此时间复杂度为 O(n)。
  • 空间复杂度:O(n)。需要额外的内存来存储队列中的元素,因此空间复杂度为 O(n)。

pop操作

  • 时间复杂度:O(1) 。
  • 空间复杂度:O(1)。

peek操作

  • 时间复杂度:O(1) 。
  • 空间复杂度:O(1)。

empty操作

  • 时间复杂度:O(1) 。
  • 空间复杂度:O(1)。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK