用栈模拟数学表达式计算

用栈模拟数学表达式计算

这类题包括数字的加减乘除运算,有基本计算器、逆波兰表达式等;

150 逆波兰表达式

逆波兰表达式
在这里插入图片描述

解题思路

这题的解题思路就是,用一个栈去存储每一个字符串,遇到数字直接入栈,遇到运算符就先做运算。

class Solution {
public:
    int to_digit(string s){
        int n=s.size();
        int sum=0;
        for(int i=0;i<n;i++){
            if('0'<=s[i]&&s[i]<='9'){
                sum=sum*10+s[i]-'0';
            }
        }
        //判断是否是负数;
        return s[0]=='-'?-1*sum:sum;
    }


    int evalRPN(vector<string>& tokens) { 
        int n=tokens.size();
        stack<int>nums;
        for(int i=0;i<n;i++){
            //先判断是否是运算符,因为运算符肯定长度只有一位;
            if(tokens[i].size()==1){
                char str=tokens[i][0];
                //如果是数字,直接入栈:
                if('0'<=str&&str<='9'){
                    nums.push(str-'0');
                //不是数字,进行运算;
                }else{
                    int a=nums.top();nums.pop();
                    int b=nums.top();nums.pop();
                    switch (str){
                        case '+':nums.push(a+b);break;
                        case '-':nums.push(b-a);break;
                        case '*':nums.push(a*b);break;
                        case '/':nums.push(b/a);break;
                    }
                }
            }
            //长度不为1,则肯定是数字,转换为数字直接入栈
            else  nums.push(to_digit(tokens[i]));
        }
        //最后的结果一定在栈顶
        return nums.top();
    }
};

224 基本计算器

基本计算器
在这里插入图片描述
解题思路:

通用的解法是利用两个栈,一个存数字,一个存运算符
在这里插入图片描述

代码实现:

class Solution {
public:
    stack<long>nums;
    stack<char>ops;
    void cal(){
        int a=nums.top();nums.pop();
        int b=nums.top();nums.pop();
        char op=ops.top();ops.pop();
        switch(op){
            case '+':nums.push(a+b);break;
            //注意这里是b-a,因为栈是先进后出
            case '-':nums.push(b-a);break;
            case '*':nums.push(a*b);break;
            case '/':nums.push(b/a);break;
        }
    }
    int calculate(string s) {
        unordered_map<char,int>mp;
        mp.insert(make_pair('+',1));
        mp.insert(make_pair('-',1))
        mp.insert(make_pair('*',2));
        mp.insert(make_pair('/',2));
        int n=s.size();
        int i=0;
        nums.push(0);
        while(i<n){
            //如果是空格,直接跳过
            if(s[i]==' '){
                i++;
                continue;
            //如果是左括号,入ops栈
            }else if(s[i]=='('){
                ops.push(s[i]);
                i++;
            //如果是右括号,计算栈内元素,直到碰到左括号
            }else if(s[i]==')'){
                while(ops.top()!='('){
                    cal();
                }
                //将左括号弹出
                ops.pop();
                i++;
            //如果是数字,可能存在45,333等数字,拼接起来存入nums;
            }else if(isdigit(s[i])){
                long d=s[i]-'0';
                int j=i+1;
                while(j<n&&isdigit(s[j])){
                    d=d*10+s[j]-'0';
                    j++;
                }
                nums.push(d);
                i=j;
            //如果是符号操作,先执行所有栈里面的操作,直到没有操作或者碰到左括号
            }else{
                //如果栈顶的优先级高于新进来的的运算符,那就先执行栈顶的运算符;
                while(!ops.empty()&&mp[ops.top()]>=mp[s[i]]){
                    cal();
                }
                ops.push(s[i]);
                i++;
            }
        }
        while(!ops.empty()){
            cal();
        }
        return nums.top();
    }
};

227 基本计算器II

基本计算器ii
在这里插入图片描述

class Solution {
public:
    stack<long>nums;
    stack<char>ops;
    void cal(){
        long a=nums.top();nums.pop();
        long b=nums.top();nums.pop();
        char c=ops.top();ops.pop();
        switch(c){
            case '+':nums.push(a+b);break;
            case '-':nums.push(b-a);break;
            case '*':nums.push(a*b);break;
            case '/':nums.push(b/a);break;
        }
    }
    int calculate(string s) {
        int n=s.size();
        unordered_map<char,int>mp;
        mp.insert(make_pair('+',1));
        mp.insert(make_pair('-',1));
        mp.insert(make_pair('*',2));
        mp.insert(make_pair('/',2));
        int i=0;
        while(i<n){
            if(s[i]==' '){
                i++;
                continue;
            }else if(isdigit(s[i])){
                long d=s[i]-'0';
                int j=i+1;
                while(j<n&&isdigit(s[j])){
                    d=10*d+s[j]-'0';
                    j++;
                }
                nums.push(d);
                i=j;
            }else{
                while(!ops.empty()&&mp[ops.top()]>=mp[s[i]]){
                    cal();
                }
                ops.push(s[i]);
                i++;
            }
        }
        while(!ops.empty()){
            cal();
        }
        return nums.top();
    }
};

1006 笨阶乘

笨阶乘
在这里插入图片描述
双栈解法

利用上面的解题思路即可解决

class Solution {
public:
    stack<int>nums;
    stack<char>ops;
    void cal(){
        int a=nums.top();nums.pop();
        int b=nums.top();nums.pop();
        char op=ops.top();ops.pop();
        switch(op){
            case '+':nums.push(a+b);break;
            //注意这里是b-a,因为栈是先进后出
            case '-':nums.push(b-a);break;
            case '*':nums.push(a*b);break;
            case '/':nums.push(b/a);break;
        }
    }
    int clumsy(int N) {
        char op[4]={'*','/','+','-'};
        unordered_map<char,int>mp;
        mp.insert(make_pair('+',1));
        mp.insert(make_pair('-',1));
        mp.insert(make_pair('*',2));
        mp.insert(make_pair('/',2));
        for(int i=N,j=0;i>0;i--,j++){
            char option=op[j%4];
            nums.push(i);
            while(!ops.empty()&&mp[option]<=mp[ops.top()]){
                cal();
            }
            if(i!=1) ops.push(option);
        }
        while(!ops.empty()) cal();
        return nums.top();
    }
};

解题思路

出现乘法、除法的时候可以把栈顶元素取出,与当前的 N进行乘法运算、除法运算(除法运算需要注意先后顺序),并将运算结果重新压入栈
出现加法、减法的时候,把减法视为加上一个数的相反数,然后压入栈,等待以后遇见「乘」「除」法的时候取出。
最后将栈里面的元素累加即为答案。

代码实现

class Solution {
public:
    int clumsy(int N) {
        stack<int>sta;
        sta.push(N);
        N--;
        int index=0;
        //遇到乘法和除法直接运算,遇到加法和减法就入栈,其中减法push相反数;
        while(N>0){
            if(index%4==0){
                sta.top()*=N;
            }else if(index%4==1){
                sta.top()/=N;
            }else if(index%4==2){
                sta.push(N);
            }else {
                sta.push(-N);
            }
            N--;
            index++;
        }
        int sum=0;
        while(!sta.empty()){
            sum+=sta.top();
            sta.pop();
        }
        return sum;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值