棧——從LeetCode題海中總結常見套路

首先記住這句話,筆試都遇到好幾次了:

從數據結構角度看,棧也是線性表!

目錄

Leetcode150.逆波蘭表達式求值

LeetCode1021.刪除最外層的括號

LeetCode921.使括號有效的最少添加

LeetCode1047.刪除字符串中的所有相鄰重複項

LeetCode面試題03.04.化棧爲隊

LeetCode682.棒球比賽

LeetCode496.下一個更大的元素I


Leetcode150.逆波蘭表達式求值

最經典的一道棧的題目,想當年爲了弄懂這題可是花了不少勁,現在看來實屬easy!

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(int i=0;i<tokens.size();i++){
                if(tokens[i]=="+"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(a+b);
                }else if(tokens[i]=="-"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(b-a);
                }else if(tokens[i]=="*"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(a*b);
                }else if(tokens[i]=="/"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(b/a);
                }else{
                        st.push(stoi(tokens[i]));
                }
        }
        return st.top();
    }
};

LeetCode1021.刪除最外層的括號

這題真妙啊,要不是看了評論區,怎麼也不會想到可以用棧來求解!

class Solution {
public:
	string removeOuterParentheses(string S) {
		string res = "";
		stack<char> mystack;
		for (int i = 0; i < S.size(); i++) {
			if (S[i] == ')')
				mystack.pop();
			if (!mystack.empty())
				res+=S[i];
			if (S[i] == '(')
				mystack.push('(');
		}
		return res;
	}
};

LeetCode921.使括號有效的最少添加

這題是上面那題的姊妹版,同樣用棧stack解決,但是注意先判斷棧是否爲空!

class Solution {
public:
    int minAddToMakeValid(string S) {
        stack<char> s;
        for(int i=0;i<S.size();i++){
            if(S[i]=='('||s.empty())//先判斷棧是否爲空
                s.push(S[i]);
            else if(S[i]==')'&&s.top()=='(')
                s.pop();
            else
                s.push(S[i]);
        }
        return s.size();
    }
};

LeetCode1047.刪除字符串中的所有相鄰重複項

想一下沒有再比這個更明顯的棧結構模擬的了……

進階一點的逆波蘭算法:棧解逆波蘭算法

class Solution {
public:
    string removeDuplicates(string S) {
        stack<char> s;
        s.push(-1);//開頭放進一個不可能的元素放置後面地址錯誤
        for(int i=0;i<S.size();i++){
            if(S[i]!=s.top())
                s.push(S[i]);
            else
                s.pop();
        }
        string ss;
        int size = s.size();
        for(int i=0;i<size-1;i++){
            ss.push_back(s.top());
            s.pop();
        }
        reverse(ss.begin(),ss.end());//結果需要反轉
        return ss;
    }
};

LeetCode面試題03.04.化棧爲隊

用兩個棧來模擬隊列,是一個十分經典的棧與隊列問題!

class MyQueue {
public:
    /** Initialize your data structure here. */
    stack<int> s1,s2;//s1記錄隊列的壓入順序,s2作轉換使用
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
    //因爲每次pop或者peek的時候都改變了s1,所以push的時候要將s2中的倒回s1
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
        s1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        int ans = s2.top();
        s2.pop();
        return ans;
    }
    
    /** Get the front element. */
    int peek() {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        return s2.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty()&&s2.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();
 */

另一種寫法:

class MyQueue {
public:
    /** Initialize your data structure here. */
    //s1記錄隊列的壓入順序,s2作轉換使用;因此s2和s1是逆序的
    stack<int> s1,s2;
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        s1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if(s2.empty()){//說明s2沒有被操作過,操作一遍
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }
        }
        int ans = s2.top();
        s2.pop();
        return ans;
    }
    
    /** Get the front element. */
    int peek() {
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }   
        }
        return s2.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty()&&s2.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();
 */

LeetCode682.棒球比賽

典型的棧,會逆波蘭算法,這個很快就會有思路

class Solution {
public:
    int calPoints(vector<string>& ops) {
        stack<int> s;
        for(int i=0;i<ops.size();i++){
            if(ops[i]=="+"){
                int a = s.top();
                s.pop();
                int b = s.top();
                s.push(a);
                s.push(a+b);
            }else if(ops[i]=="C"){
                s.pop();
            }else if(ops[i]=="D"){
                int c = s.top();
                s.push(2*c);
            }else{
                //牢記將string轉換成int的方法!
                s.push(stoi(ops[i]));
            }
        }
        int ans = 0;
        while(!s.empty()){
            ans+=s.top();
            s.pop();
        }
        return ans;
    }
};

LeetCode496.下一個更大的元素I

感覺不用用棧就可以做啊

官方題解用單調棧+hashmap,有點小題大做了

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> v;
        for(int i=0;i<nums1.size();i++){
            bool flag = true;
            for(int j = 0;j<nums2.size();j++)
                if(nums2[j]==nums1[i])
                    for(int k = j+1;k<nums2.size();k++)
                        if(nums2[k]>nums1[i]){
                            v.push_back(nums2[k]);
                            flag = false;
                            break;
                        }
            if(flag)
                v.push_back(-1);
        }
        return v;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章