LeetCode 770. Basic Calculator IV题目解析

转载源:戳这里

题目解析

此题是LeetCode 772的加强版,我们依然使用递归下降法来解决这个问题,文法如下:

  1. exp := exp +|- additive | additive

  2. additive := additive * factor | additive

  3. factor := num | (exp) | variable(变量)

我们使用vector<string>类型来表示表达式的结果,该容器中元素之间的关系是相加,比如vector<string> res = ["a", "10"],表示表达式"a+10"。这样只需要在additive函数中处理相乘,在exp函数中处理合并同类项即可。

本地调试模板

class Solution {
public:
 
    string token;
    string str;
    int index;
 
    vector<string> g_evalvars;
    vector<int> g_evalints;
 
 
    //找出下一个符号 + - * ( ) 数字或者变量
    string get_token() {
        while(str[index]==' ') index++;  //去除空格
        string token = "";
        if(index == str.length()) return token;
        //数字
        if(str[index]>='0' && str[index]<='9') {
            while(str[index]>='0' && str[index]<='9') {
                token += str[index];
                index++;
            }
        }else if(str[index]>='a' && str[index]<='z') {  //变量
            while(str[index]>='a' && str[index]<='z') {
                token += str[index];
                index++;
            }
        }else
        switch(str[index]) {
            case '+':
                token += "+";
                index++;
                break;
            case '-':
                token += "-";
                index++;
                break;
            case '*':
                token += "*";
                index++;
                break;
            case '/':
                token += "/";
                index++;
                break;
            case '(':
                token += '(';
                index++;
                break;
            case ')':
                token += ')';
                index++;
                break;
            default:  //不可识别的记号
                break;
        }
        return token;
    }
    //判断是否为num
    bool is_num(string &tk) {
        for(int i=0; i<tk.length(); i++)
            if(tk[i]>='a' && tk[i]<='z') return false;
        return true;
    }
    string int2str(const int int_temp)
    {
        string string_temp;
        stringstream stream;
        stream<<int_temp;
        string_temp=stream.str();   //此处也可以用 stream>>string_temp
        return string_temp;
    }
    //使用c分割字符串s
    void split_string(const string& s, const string& c, vector<string> &v){
        string::size_type pos1, pos2;
        pos2 = s.find(c);
        pos1 = 0;
        while(string::npos != pos2){
            v.push_back(s.substr(pos1, pos2-pos1));
 
            pos1 = pos2 + c.size();
            pos2 = s.find(c, pos1);
        }
        if(pos1 != s.length())
            v.push_back(s.substr(pos1));
    }
    //分离因子的系数和变量
    void split(const string &fac1, string &num1, string &vars1) {
        int i = 0;
        while(i<fac1.length() && fac1[i]!='*') i++;
        num1 = fac1.substr(0, i);
        if(i != fac1.length())
            vars1 = fac1.substr(i+1, fac1.length()-i-1);
    }
    //处理两个因子相乘 1*a*b*c * 2*c*d
    string multi(string fac1, string fac2) {
        string res = "";
        string num1, vars1, num2, vars2;
        int coff;
        split(fac1, num1, vars1);
        split(fac2, num2, vars2);
        coff = atoi(num1.c_str()) * atoi(num2.c_str());
 
        vector<string> vvars1, vvars2;
        split_string(vars1, "*", vvars1);
        split_string(vars2, "*", vvars2);
        sort(vvars1.begin(), vvars1.end());
        sort(vvars2.begin(), vvars2.end());
 
        res += int2str(coff);
        int s1 = 0, s2 = 0;
        while(s1<vvars1.size() && s2<vvars2.size()) {
            if(vvars1[s1] < vvars2[s2]) {
                res += "*";
                res += vvars1[s1];
                s1++;
            }else {
                res += "*";
                res += vvars2[s2];
                s2++;
            }
        }
        while(s1<vvars1.size()) {
            res += "*";
            res += vvars1[s1++];
        }
        while(s2<vvars2.size()) {
            res += "*";
            res += vvars2[s2++];
        }
        return res;
    }
    //排序辅助函数
    static bool cmp(const string &s1, const string &s2) {
        int nums1 = 0, nums2 = 0;  //两因子的度
        for(int i=0; i<s1.length(); i++) if(s1[i] == '*') nums1++;
        for(int i=0; i<s2.length(); i++) if(s2[i] == '*') nums2++;
        if(nums1 != nums2) return nums1 > nums2; //度大的优先
        else {
            string vars1, vars2;
            int i = 0;
            while(i<s1.length() && s1[i]!='*') i++;
            if(i != s1.length()) vars1 = s1.substr(i+1, s1.length()-i-1);
            i = 0;
            while(i<s2.length() && s2[i]!='*') i++;
            if(i != s2.length()) vars2 = s2.substr(i+1, s2.length()-i-1);
            return vars1 < vars2;   //字典序排序
        }
    }
    //合并同类项
    void merge_factor(vector<string> &res, vector<string> &res1) {
        if(res.size() == 0) return ;
 
        sort(res.begin(), res.end(), cmp);
        int c;
        string num;
        string var;
        for(int i=0; i<res.size(); i++) {
            if(i == 0) {
                split(res[0], num, var);
                c = atoi(num.c_str());
            }else {
                string t_num, t_var;
                split(res[i], t_num, t_var);
                if(t_var == var) c += atoi(t_num.c_str());
                else {
                    if(c != 0) {
                        string tp = int2str(c);
                        if(var != "")   tp += "*"+var;
                        res1.push_back(tp);
                    }
                    num = t_num;
                    var = t_var;
                    c = atoi(num.c_str());
                }
            }
        }
        if(c != 0) { //插入系数非0项
            string tp = int2str(c);
            if(var != "")   tp += "*"+var;
            res1.push_back(tp);
        }
        return ;
    }
 
    vector<string> exp() {
        vector<string> res = additive();
        vector<string> temp;
        while(token=="+" || token=="-") {
            string op = token;
            token = get_token();    //跳过'+' '-'
            temp = additive();
            if(op=="+") {
                for(int i=0; i<temp.size(); i++) res.push_back(temp[i]);
            }else {
                for(int i=0; i<temp.size(); i++) res.push_back(multi(temp[i], "-1"));
            }
        }
        vector<string> res1;
        //合并同类项
        merge_factor(res, res1);
        return res1;
    }
    vector<string> additive() {
        vector<string> res = factor();
        while(token=="*") {
            token = get_token();   //跳过'*'
            vector<string> fac= factor();
            vector<string> temp;
            //执行相乘运算
            for(int i=0; i<res.size(); i++)
            for(int j=0; j<fac.size(); j++) {
                temp.push_back(multi(res[i], fac[j]));
            }
            res = temp;
        }
        return res;
    }
    vector<string> factor() {
        vector<string> res;
        if(token == "(") {
            token = get_token();
            res = exp();
            token = get_token();  //跳过')'
        }else {
            if(is_num(token)) {
                res.push_back(token);
            }else {
                for(int i=0; i<g_evalvars.size(); i++)
                    if(token == g_evalvars[i])
                        res.push_back(int2str(g_evalints[i]));
                if(res.size() == 0) {
                    string t = "";
                    t += "1*";
                    t += token;
                    res.push_back(t);
                }
            }
            token = get_token();  //跳过num
        }
        return res;
    }
    vector<string> basicCalculatorIV(string expression, vector<string>& evalvars, vector<int>& evalints) {
        vector<string> res;
        str = expression;
        g_evalvars = evalvars;
        g_evalints = evalints;
        index = 0;
        token = get_token();
        res = exp();
        return res;
    }
};


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值