棧與隊列經典面試題:用兩個棧實現隊列、用兩個隊列實現棧

用兩個棧實現隊列、用兩個隊列實現棧

題1:用兩個棧實現隊列

算法分析

棧的特色是先進後出,而隊列的特色是先進先出。那麼如何用棧來實現隊列呢?算法

先看第一個棧:緩存

1 2 3 4ide

根據先進後出原則,逐個出棧而後存儲到下一個棧:設計

4 3 2 1code

此時,再進行出棧,輸出的將是:blog

4 3 2 1隊列

這和最原始的棧內存「1 2 3 4」的隊列化輸出結果:「4 3 2 1」一致了!也就是,先進來的4元素,也先出去了!圖片

算法設計

設計兩個棧,第一個棧做爲數據棧用於存儲數據,第二個棧用於反轉順序!內存

對於由兩個棧實現的隊列,若是要返回隊首的時候,就將第一個數據棧把數據都扔給第二個反轉棧用於反轉,隨後就可讓先進來的棧尾元素到達棧首,此時返回棧首其實就是返回隊首!element

須要注意的是:

  1. 每次出隊列前,都須要清空第一個數據棧,放到反轉棧,這是爲了保持次序
  2. 出隊列結束後,爲了下一個元素入進入隊列順序不亂,還須要讓反轉棧的元素從新倒回數據棧

題目描述和AC代碼

在這裏插入圖片描述

class MyQueue {
private:
    stack<int> inStk;
    stack<int> outStk;

    void turnToStack(stack<int>& inStk, stack<int>& outStk) {
        while (!outStk.empty()) {
            inStk.push(outStk.top());
            outStk.pop();
        }
    }
public:
    /** Initialize your data structure here. */
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        inStk.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        turnToStack(outStk, inStk);
        int ret = outStk.top();
        outStk.pop();
        turnToStack(inStk, outStk);
        return ret;
    }
    
    /** Get the front element. */
    int peek() {
        turnToStack(outStk, inStk);
        int ret = outStk.top();
        turnToStack(inStk, outStk);
        return ret;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return inStk.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();
 * bool param_4 = obj->empty();
 */

在這裏插入圖片描述

題2:用兩個隊列實現棧

爲了能讓隊列實現棧,可否藉助棧實現隊列的思路進行反轉呢?答案是否認的!

由於隊列壓根起不到反轉的效果,因而這裏須要從新設計算法!

算法分析

對於一個棧:

1 2 3 4

首先輸出的應該是 1 ,由於 1 是最後一個進來的,要先出去!

那麼,先用一個數據隊列存儲棧元素,隊列的元素序列是

1 2 3 4

可是此時的隊首是 4 而不是 1 怎麼辦呢?

再設計一個轉存隊列,用於存儲隊尾前的所有元素,例如:

2 3 4

這時候,數據隊列裏就只有 1 這一個元素了,此時的隊首就是棧首!而後處理完後,再將轉存隊列的內容返回到數據隊列中,由於隊列不會改變次序,因此數據隊列會成爲:

2 3 4

這就是刪除棧首的結果!

算法設計

設計兩個隊列,一個數據隊列,一個緩存隊列。

第一個數據隊列存儲棧數據,當須要彈棧的時候,將數據隊列除了最後一個元素之外的數據都放到緩存隊列!而後數據隊列就只有一個元素了,就是最後進入的那個元素,就直接彈出便可,此時就實現了 「後進先出」

須要注意的是:

  1. 緩存只能緩存前 n - 1 個元素,不能把要彈棧的元素都緩存了
  2. 彈棧完成後,要將緩存的內容倒回數據隊列,不然下一個數據入棧的時候,順序會亂

題目描述及AC代碼

在這裏插入圖片描述

class MyStack {
private:
    queue<int> inQue;
    queue<int> outQue;
public:
    /** Initialize your data structure here. */
    MyStack() {

    }
    
    /** Push element x onto stack. */
    void push(int x) {
        inQue.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        while (1 != inQue.size()) {
            outQue.push(inQue.front());
            inQue.pop();
        }
        int ret = inQue.front();
        inQue.pop();
        while (!outQue.empty()) {
            inQue.push(outQue.front());
            outQue.pop();
        }
        return ret;
    }
    
    /** Get the top element. */
    int top() {
        while (1 != inQue.size()) {
            outQue.push(inQue.front());
            inQue.pop();
        }
        int ret = inQue.front();
        outQue.push(inQue.front());
        inQue.pop();
        while (!outQue.empty()) {
            inQue.push(outQue.front());
            outQue.pop();
        }
        return ret;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return inQue.empty();
    }
};

/**
 * 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();
 * bool param_4 = obj->empty();
 */

在這裏插入圖片描述

相關文章
相關標籤/搜索