递归与栈(Stack):解决表达式求值

栈基础知识

  • 先入后出
  • 可以处理具有完全包含关系的问题

经典的栈实现方法

class Stack{
	public:
        Stack(){}
        void push(int x){
            data.push_back(x);
            return;
        }
        void pop(){
            if(empty()) return;
            data.pop_back();
        }
        bool empty(){
            return data.size() == 0;
        }
        int size(){
            return data.size();
        }
        void output(){
            cout << "=====" << endl;
            for(int i = data.size() - 1; i >= 0; i--){
                cout << "" << data[i] <<endl;
            }
            cout << "=====" << endl;
        }
	
	private:
		vector<int> data;
};

int main(){
    Stack s;
    string op;
    int val;
    while(cin >> op){
        if(op == "push"){
            cin >> val;
            s.push(val);
        }else if(op == "pop"){
            s.pop();
        }else if(op == "size"){
            cout << "size: " << s.size() << endl;
        }else if(op == "output"){
            s.output();
        }
    }
}

栈的典型应用场景

场景一:操作系统中的线程栈
场景二:表达式求值

经典面试题 - 栈的基本操作

03.04.化栈为队

  • 设置两个栈 s1,s2
  • 第二个栈可以实现对第一个栈内的反序
  • 入队列永远从s2入
  • 出队列永远从s1出,如果s1空了,就将s2的元素反序入s1
class MyQueue {
public:
    stack<int> s1,s2;
    MyQueue() {}

    void push(int x) {
        s2.push(x);
        return;
    }

    void transfer(){
        if(!s1.empty()) return;
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
        return;
    }
    
    int pop() {
        transfer();
        int ret = s1.top();
        s1.pop();
        return ret;
    }
    
    int peek() {
        transfer();
        return s1.top();
    }
    
    bool empty() {
        return s1.empty() && s2.empty();
    }
};

682.棒球比赛

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] == "D"){
                s.push(2 * s.top());
            }else if(ops[i] == "C"){
                s.pop();
            }else{
                s.push(atoi(ops[i].c_str()));
            }
        }
         int sum = 0;
        while (!s.empty()){
            sum += s.top();
            s.pop();
        }
        return sum;
    }
};

844.比较退格的字符串

class Solution {
public:
    void transform(string S, stack<char> &s){
        for(int i = 0 ; i < S.size(); i++){
            if(S[i] == '#' && !s.empty()) s.pop();
            else if(S[i] != '#') s.push(S[i]);
        }
        return;
    }
    bool backspaceCompare(string S, string T) {
        stack<char> s;
        stack<char> t;
        transform(S, s);
        transform(T, t);
        if(s.size() - t.size()) return false;
        while(!s.empty()){
            if(s.top() != t.top()) return false;
            s.pop();
            t.pop();
        }
        return true;
    }
};

946.验证栈序列

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> s;
        for(int i = 0, j = 0; i < popped.size(); i++){
            while(j < pushed.size() && (s.empty() || s.top() != popped[i])){
                s.push(pushed[j]);
                j += 1;
            }
            if(s.top() != popped[i]) return false;
            s.pop();
        }
        return true;
    }
};

经典面试题-栈结构扩展应用

20.有效的括号

class Solution {
public:
    bool isValid(string s) {
        stack<char> ss;
        for(int i = 0; i < s.size(); i++){
            switch(s[i]){
                case '(':
                case '[':
                case '{': ss.push(s[i]); break;
                case ')': if(ss.empty() || ss.top() != '(') return false; ss.pop(); break;
                case ']': if(ss.empty() || ss.top() != '[') return false; ss.pop(); break;
                case '}': if(ss.empty() || ss.top() != '{') return false; ss.pop(); break;
            }
        }
        return ss.empty();
    }
};

1021.删除最外层的括号

  • 遇上左括号加1,遇上右括号减1
  • 直到0的时候即为分界点
class Solution {
public:
    string removeOuterParentheses(string s) {
        string ret;
        for(int i = 0, pre = 0, cnt = 0; i < s.size(); i++){
            if(s[i] == '(') cnt += 1;
            else cnt -= 1;
            if(cnt != 0) continue;
            ret += s.substr(pre + 1, i - pre -1);
            pre = i + 1;
        }
        return ret;
    }
};

145.二叉树的后续遍历

  • 前续遍历:根 左 右
  • 中续遍历:左 根 右
  • 后续遍历:左 右 根
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(root == nullptr) return vector<int>();
        vector<int> ans;
        stack<TreeNode *> s1;
        stack<int> s2;
        s1.push(root);
        s2.push(0);
        while(!s1.empty()){
            int status = s2.top();
            s2.pop();
            switch(status){
                case 0: {
                    s2.push(1);
                    if(s1.top()->left != nullptr){
                        s1.push(s1.top() -> left);
                        s2.push(0);
                    }
                }break;
                case 1:{
                    s2.push(2);
                     if(s1.top()->right != nullptr){
                        s1.push(s1.top() -> right);
                        s2.push(0);
                    }
                }break;
                case 2:{
                    ans.push_back(s1.top()->val);
                    s1.pop();
                }break;
            }
        }
        return ans;
    }
};

331.验证二叉树的前序序列化

  • x ## 可以缩略为 #
  • 最后所有内容只要可以缩略为#,即为二叉树的前序序列化
class Solution {
public:
    bool isValidSerialization(string preorder) {
       vector<string> s;
       for(int i = 0, j = 0; i < preorder.size(); i = j + 1){
           j = i;
           while(j < preorder.size() && preorder[j] != ',') ++j;
           s.push_back(preorder.substr(i, j-i));
           int last = s.size() - 1;
           while(s.size() >= 3 && s[last] == "#" && s[last-1] == "#"){
               s[last - 2] = "#";
               s.pop_back();
               s.pop_back();
               last = s.size() -1;
           }
           if(s.size() == 2 && s[0] == "#" && s[1] == "#") return false;
       }
       return s.size() == 1 && s[0] == "#";
    }
};

227.基本计算器ii

  • 增加两个栈,一个为num存放数字,另一个为ops存放运算符
  • 如果遇到比之前优先级小的运算符,先运算之前优先级大的结果弹出,再入栈新的运算符
  • 最后清空栈,从运算符栈中依次计算,最后数字栈中留存的数字就是计算的结果
class Solution {
public:
    int level(char c){
        switch(c){
            case '@': return -1;
            case '+':
            case '-': return 1;
            case '*':
            case '/': return 2;
        }
        return 0;
    }
    int calc(int a, char op, int b){
        switch(op){
            case '+': return a + b;
            case '-': return a - b;
            case '*': return a * b;
            case '/': return a / b;
        }
        return 0;
    }
    int calculate(string s) {
        stack<int> num;
        stack<char> ops;
        s += "@";
        for (int i = 0, n = 0; i < s.size(); i++){
            if(s[i] == ' ') continue;
            if(level(s[i]) == 0){
                n = n * 10 + (s[i] - '0');
                continue;
            }
            num.push(n);
            n = 0;
            while(!ops.empty() && level(s[i]) <= level(ops.top())){
                int b = num.top(); num.pop();
                int a = num.top(); num.pop();
                num.push(calc(a, ops.top(), b));
                ops.pop();
            }
            ops.push(s[i]);
        }
        return num.top();
    }
};

636.函数的独占时间

class Solution {
public:
    vector<int> exclusiveTime(int n, vector<string>& logs) {
        vector<int> ans(n);
        stack<int> vID;
        for(int i = 0, pre = 0; i < logs.size(); i++){
            int pos1 = logs[i].find_first_of(":");
            int pos2 = logs[i].find_last_of(":");
            string id_str = logs[i].substr(0, pos1);
            string status = logs[i].substr(pos1 + 1, pos2 - pos1 -1);
            string time_str = logs[i].substr(pos2 + 1, logs[i].size());
            int id = atoi(id_str.c_str());
            int time_stamp = atoi(time_str.c_str());
            if(status == "start"){
                if(!vID.empty()){
                    ans[vID.top()] += time_stamp - pre;
                }
                pre = time_stamp;
                vID.push(id);
            } else {
                ans[id] += time_stamp - pre + 1;
                pre = time_stamp + 1;
                vID.pop();
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值