程式碼隨想錄第10天 | 棧與佇列part01

跳圈發表於2024-06-17

題目:232.用棧實現佇列

思路:

1.使用雙棧,一個作為輸入,一個作為輸出

程式碼:

class MyQueue {
private:
    stack<int> A,B;
public:
    MyQueue() {
    }
    void push(int x) {
        A.push(x);
    }
    int pop() {  //刪除A棧底元素 並返回元素
        int result=this->peek();
        B.pop();
        return result;
    }    
    int peek() {  //獲取A棧底元素
        if(B.empty()){
            while(!A.empty()){
                B.push(A.top());
                A.pop();
            }
        }
        return B.top();
    }
    bool empty() {//最佳化-> return A.empty()&& B.empty;
        if(A.empty()&&B.empty())
            return true;
        else
            return false;    
    }
};

補充:

1.棧和佇列是STL(C++標準庫)裡面的兩個資料結構。常使用SGI STL版(開源,可讀性高,被GCC所採用)。
2.二者以底層容器來實現所有工作,對外提供統一介面,所以二者不是容器,屬於container adapter 容器介面卡。
3.因二者的進出特性,不提供迭代器進行訪問。
棧stack
stack<型別> 變數名;

  1. 一頭通,先進後出
  2. 底層實現可使用容器deque,vector,list,沒有指定底層實現,預設deque為預設情況下棧的底層結構
    deque是一個雙向佇列,封住一段,只開通另一端就可以實現棧的邏輯了。
  3. 對外提供介面
    push(x) -- 元素 x 入棧、
    empty() -- 返回棧是否為空
    pop() -- 移除棧頂元素
    top() -- 獲取棧頂元素
    size() -- 返回棧內元素的大小;
可以指定vector為棧的底層實現,初始化語句如下:
std::stack<int, std::vector<int> > third;  // 使用vector為底層容器的棧

佇列queue

  1. 兩頭通,先進先出
  2. SGI STL中佇列一樣是以deque為預設情況下的底部結構
  3. 對外提供介面
    push(x) -- 在末尾加入一個元素
    empty() -- 如果佇列空則返回真
    front() -- 返回第一個元素
    pop() -- 刪除第一個元素
    back() -- 返回最後一個元素
    size() -- 返回佇列中元素的個數
可以指定list 為起底層實現,初始化queue的語句如下:
std::queue<int, std::list<int>> third; // 定義以list為底層容器的佇列

題目:225. 用佇列實現棧

思路:

0.兩個佇列,第二個用來備份除隊尾元素以外的元素
1.兩個佇列,入隊的時候不斷調整,使的後存入的元素在隊首 模擬棧的存入
2.一個佇列實現,頭插尾 ,一直插,最後尾為首 彈出

程式碼:

方法一

class MyStack {
private:
    queue<int> queueA,queueB;
public:
    MyStack() {
    }
    void push(int x) {  //輸入調整,使得隊首為最新加入的元素 模擬棧
        queueB.push(x);
        while(!queueA.empty()){
            queueB.push(queueA.front());
            queueA.pop();
        }
        while(!queueB.empty()){
            queueA.push(queueB.front());
            queueB.pop();
        }
    }
    int pop() { //移除並返回隊首元素
        int result=queueA.front();
        queueA.pop();
        return result;
    }    
    int top() {//返回隊首元素
        return queueA.front();
    }   
    bool empty() {
        return queueA.empty();
    }
}; *

方法二
來源隨想錄

class MyStack {
public:
    queue<int> que1;
    queue<int> que2; // 輔助佇列,用來備份
    /** Initialize your data structure here. */
    MyStack() {

    }
    /** Push element x onto stack. */
    void push(int x) {
        que1.push(x);
    }
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que1.size();
        size--;
        while (size--) { // 將que1 匯入que2,但要留下最後一個元素
            que2.push(que1.front());
            que1.pop();
        }
        int result = que1.front(); // 留下的最後一個元素就是要返回的值
        que1.pop();
        que1 = que2;            // 再將que2賦值給que1
        while (!que2.empty()) { // 清空que2
            que2.pop();
        }
        return result;
    }
    /** Get the top element. */
    int top() {
        return que1.back();
    }
    /** Returns whether the stack is empty. */
    bool empty() {
        return que1.empty();
    }
};

題目:20. 有效的括號

思路:

0.利用棧存入,遇到不同邊的的括號就彈出,左括號新增,右括號彈出

坑:

  1. 缺少 第一個為右括號的情況 即沒有匹配的括號,此時stack為空
  2. stack有empty()判空
  3. 不匹配的情況可以合併一下
class Solution {
public:
    bool isValid(string s) {
        //奇數 直接false
        if(s.size()%2!=0)
            return false;
        stack <char> stack;
        for(char c: s){
            //入棧時直接存入對應的右括號 方便比較
            if(c=='(')  stack.push(')');
            else if(c=='{')  stack.push('}');
            else if(c=='[')  stack.push(']');
            else if(c==')'||c=='}'||c==']'){
                //不透過,缺少第一個為右括號的情況, 最佳化一下,合併不相等的情況
                if(stack.size()==0||c!=stack.top()) 
                    return false;
                if(c==stack.top())
                    stack.pop();
            }
        }
        return stack.empty();
        /* 囉嗦,已經有empty了啊
        if(stack.size()==0) 
            return true;
        else 
            return false;
        */
    }
};

題目:1047. 刪除字串中的所有相鄰重複項

思路:

  1. 利用棧,比較存入元素和棧頂元素是否相等,相等刪除,最後將棧內的結果存入新的字串中,別忘了翻轉,棧是後進先出
    時間複雜度: O(n)
    空間複雜度: O(n)

坑:

  1. reveres();
class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> stack;
        for(char c: s){
            if(stack.size()!=0&&c==stack.top())
                stack.pop();
            else 
                stack.push(c);
        }
        //啊哈,棧存入字串是倒序,那麼翻轉就解決了
        string result;
        while(!stack.empty()){
            result.push_back(stack.top());
            stack.pop();
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

補充:

reverse(s.begin(),s.end())是C++庫函式

今日總結

涉及左右,相鄰匹配的問題,使用棧

相關文章