LintCode 368: Expression Evaluation (逆波兰表达式的应用,难题!)

  1. Expression Evaluation
    中文English
    Given an expression string array, return the final result of this expression

Example
Example 1:

For the expression 2*6-(23+7)/(1+2),
Input:
[“2”, “*”, “6”, “-”, “(”,“23”, “+”, “7”, “)”, “/”, “(”, “1”, “+”, “2”, “)”]
Output:
2
Example 2:

For the expression 4-(2-3)*2+5/5,
Input:
[“4”, “-”, “(”, “2”,“-”, “3”, “)”, “*”, “2”, “+”, “5”, “/”, “5”]
Output:
7
Notice
The expression contains only integer, +, -, *, /, (, ).

解法1:
先转换成逆波兰表达式,然后再将字符逐个压栈,出栈,根据操作符类型来计算值。
代码如下:

class Solution {
public:

    /**
     * @param expression: a list of strings
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        int result = 0;
        vector<string> RPN = convertToRPN(expression);
        
        stack<string> stk;
        
        for (auto s : RPN) {
            if (s == "+" || s == "-" || s == "*" || s == "/") {
                int a = stoi(stk.top());
                stk.pop();
                int b = stoi(stk.top());
                stk.pop();
                
                if (s == "+") stk.push(to_string(a + b));
                if (s == "-") stk.push(to_string(b - a));
                if (s == "*") stk.push(to_string(a * b));
                if (s == "/") stk.push(to_string(b / a));
            } else {
                stk.push(s);
            }
        }
        
        if (stk.empty()) return 0;
        else {
            result = stoi(stk.top());
            stk.pop();
            return result;
        }
    }

private:
    int getLevel(string opt) {
        if (opt == "(")
            return 0;
        if (opt == "+" || opt == "-")
            return 1;
        if (opt == "*" || opt == "/")
            return 2;

        return 3;
    }

    bool isOperator(string c) {
        return (c == "+" || c == "-" || c == "*" || c == "/");
    }
    //create reverse polish notation string
    vector<string> convertToRPN(vector<string> &expression) {
        stack<string> st;
        vector<string> RPN;
        int len = expression.size();
        for (int i = 0; i < len; ++i) {
            string c = expression[i];
            if (c == "(")
                st.push(c);
            else if (c == ")") {
                while (st.top() != "(") {
                    RPN.push_back(st.top());
                    st.pop();
                }
                st.pop();
            } else {
                if (!isOperator(c))
                    st.push(c);
                else {
                    while (!st.empty() && getLevel(st.top()) >= getLevel(c)) {
                            RPN.push_back(st.top());
                            st.pop();
                    }
                    st.push(c);
                }
            }
        }

        while (! st.empty()) {
            RPN.push_back(st.top());
            st.pop();
        }

        return RPN;
    }
};

注意波兰表达式是前缀,逆波兰表达式是后缀。两个里面都不需要再有括号了!

二刷:

class Solution {
public:
    /**
     * @param expression: a list of strings
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        int len = expression.size();
        if (len == 0) return 0;
        stack<string> optrStk;
        vector<string> RPNExpr;
        map<string, int> prio;
        prio["+"] = 1;
        prio["-"] = 1;
        prio["*"] = 2;
        prio["/"] = 2;
        for (int i = 0; i < len; i++) {
            string str = expression[i];
            if (str.size() > 1 || str[0] >= '0' && str[0] <= '9') {
                RPNExpr.push_back(str);
                continue;
            }
            if (str == "(") {
                optrStk.push(str);
                continue;
            }
            if (str == ")") {
                while (!optrStk.empty() && optrStk.top() != "(") {
                    RPNExpr.push_back(optrStk.top());
                    optrStk.pop();
                }
                optrStk.pop(); //pop out the "("
                continue;
            }
            while (!optrStk.empty() && prio[optrStk.top()] >= prio[str]) {
                RPNExpr.push_back(optrStk.top());
                optrStk.pop();
            }
            optrStk.push(str);
        }
        //push the rest in optrStk to RPNExpr
        while (!optrStk.empty()) {
            RPNExpr.push_back(optrStk.top());
            optrStk.pop();
        }
        //Now evaluate RPNExpr
        len = RPNExpr.size();
        if (len == 0) return 0;
        stack<int> RPNStk;
        for (int i = 0; i < len; i++) {
            string str = RPNExpr[i];
            if (str.size() > 1 || str[0] >= '0' && str[0] <= '9') {
                RPNStk.push(stoi(str));
                continue;
            }
            int top1 = RPNStk.top(); RPNStk.pop();
            int top2 = RPNStk.top(); RPNStk.pop();
            if (str == "+") {
                RPNStk.push(top2 + top1);
            } else if (str == "-") {
                RPNStk.push(top2 - top1);
            } else if (str == "*") {
                RPNStk.push(top2 * top1);
            } else {
                RPNStk.push(top2 / top1);
            }
        }
        return RPNStk.top();
    } 
};

解法2:用递归。每次从优先级最低的运算符开始处理。如果有左括号,优先级加100,如果有右括号,优先级减100.

class Solution {
public:
    /**
     * @param expression: a list of strings
     * @return: an integer
     */
    int evaluateExpression(vector<string> &expression) {
        int res;
        int expSize = expression.size();
        res = evaluate(expression, 0, expSize - 1);
        return res;        
    }
private:
    int evaluate(vector<string> &expression, int start, int end) {
        if (start > end) return 0;
        #define INF 0x3f3f3f3f
        int lowestPrio = INF - 1; //这里是针对运算符的优先级而言,比常数项的优先级低一点就可以。
        int lowestPrioPos = -1;
        int expSize = expression.size();
        int tmpPrio = 0;
        for (int i = start; i <= end; i++) {
            string curStr = expression[i];
            int curPrio = INF; //注意这里默认常数项的优先级无限高。
            if (curStr == "(") {
                tmpPrio += 100;
            } else if (curStr == ")") {
                tmpPrio -= 100;
            } else if (curStr == "+" || curStr == "-") {
                curPrio = tmpPrio + 1;
            } else if (curStr == "*" || curStr == "/") {
                curPrio = tmpPrio + 2;
            }
            if (curPrio <= lowestPrio) {
                lowestPrio = curPrio;
                lowestPrioPos = i;
            }
        }
        if (lowestPrioPos == -1) { //It is a number. 
            int left = start, right = end;
            while (left <= right && (expression[left] == "(" || expression[left] == ")")) left++;
            while (left <= right && (expression[right] == "(" || expression[right] == ")")) right--;
            //here if not all brackets, left and right should be the same
            if (left != right) return 0;
            return stoi(expression[left]);
        }
       
        int leftEvaluate = evaluate(expression, start, lowestPrioPos - 1);
        int rightEvaluate = evaluate(expression, lowestPrioPos + 1, end);
        string lowestPrioOpt = expression[lowestPrioPos];
        
        if (lowestPrioOpt == "+") {
            return leftEvaluate + rightEvaluate;
        } else if (lowestPrioOpt == "-") {
            return leftEvaluate - rightEvaluate;
        } else if (lowestPrioOpt == "*") {
            return leftEvaluate * rightEvaluate;
        } else if (lowestPrioOpt == "/") {
            return leftEvaluate / rightEvaluate;
        } 
        return -1;        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值