day11 | 第五章 栈与队列part02

20. 有效的括号

这个题目并没有优先级的考虑,只需要匹配好括号就可以了。左括号是怎么来的,那么右括号就是怎么匹配上的,感觉这里解释起来就很抽象,用栈就很直观的解决了,但是不知道该怎么解释如何想到的?左括号是进栈,右括号是对应着消除,退栈。

class Solution {
public:
    bool isValid(string s) {
        stack<char> stk;
        for(auto& c : s) {
            switch(c) {
                case '(': stk.push(c); 
                break;
                case '[': stk.push(c);
                break;
                case '{': stk.push(c);
                break;
                case ')': {
                    if(stk.empty() || stk.top() != '(') {
                        return false;
                    }
                    else {
                        stk.pop();
                    }
                }
                break;
                case ']': {
                    if(stk.empty() || stk.top() != '[') {
                        return false;
                    }
                    else {
                        stk.pop();
                    }
                }
                break;
                case '}':
                {
                    if(stk.empty() || stk.top() != '{') {
                        return false;
                    }
                    else {
                        stk.pop();
                    }
                }
            }
        }
        return stk.empty();
    }
};

1047. 删除字符串中的所有相邻重复项

思考这样一个问题,如果从左往右去遍历整个字符串,依次将字符入栈,则当前字符和栈顶的关系就是当前字符和它前面相邻字符的关系,也就是题目所考虑的相邻字符的关系。
这题使用数组模拟栈,效率更高

class Solution {
public:
    string removeDuplicates(string s) {
        const int N = s.size();
        char stk[N];
        int tt  = -1;
        for(auto& c : s) {
            if(tt == -1) {
                stk[++tt] = c;
            }
            else {
                auto top = stk[tt];
                if(top == c) {
                    --tt;
                }
                else {
                    stk[++tt] = c;
                }
            }
        }
        string ret = "";
        while(tt != -1) {
            ret += stk[tt--];
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

150. 逆波兰表达式求值

经典的栈使用的题目,需要注意的是,依次弹出两个操作数a, b是将a放在后面,比如我们现在遇到了运算符 /,现在需要弹出两个操作数a, b,则我们需要运算是b/a
另外这道题给的范围数字可以到200,长度到\(10^4\)如果全是乘法那就是\(200^{10000}\)是会爆int的,所以我们的结果和运算过程要用long算,整体思路就是遇到数字直接进栈,遇到运算符就弹出两个数字运算,算完了又弹进去。

class Solution {
public:
    inline bool judge(string& s) {
        return s != "/" && s != "*"&& s != "-"&& s != "+";
    }
    int evalRPN(vector<string>& tokens) {
        stack<long> stk;
        for(auto& token:tokens) {
            if(judge(token)) {
                stk.push(atoi(token.c_str()));
            }
            else {
                long a = stk.top();
                stk.pop();
                long b = stk.top();
                stk.pop();
                switch(token[0]) {
                    case '+': stk.push(b + a);break;
                    case '-': stk.push(b - a);break;
                    case '*': stk.push(b * a);break;
                    case '/': stk.push(b / a);break;
                }
            }
        }
        return stk.top();
    }
};
posted @ 2024-02-06 12:12  ccnju  阅读(22)  评论(0)    收藏  举报