【leetcode】227. Basic Calculator II

题目:
Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero.


思路:
设置两个栈nums_stack和opt_stack。nums_stack存放数字,opt_stack存放运算符。如果当前运算符比前一个运算符的优先级更大,则将当前运算符压入opt_stack中;否则,先对前一个运算符进行计算,从nums_stack取出两个数字,计算结果再压入nums_stack中。也就是说,opt_stack从栈底到栈顶存放的运算符的优先级是从低到高的(也不会存放优先级相等的运算符)。最后,如果opt_stack不为空,逐个弹出并运算就好了。

后来我发现,其实nums_stack最多也就3个元素,opt_stack最多也就2个元素,所以不用麻烦STL了,自己用小小的数组设计了一个固定容量的stack,效率稍稍有所提升。


代码实现:
优化之前:

class Solution {
public:
    bool isOpt(char c){
        if (c == '+' || c == '-' || c == '*' || c == '/'){
            return true;
        }
        return false;
    }
    
    bool isNum(char c){
        if (c >= '0' && c <= '9'){
            return true;
        }
        return false;
    }
    
    int getNumEnd(string &s, int begin){
        while (begin < s.size() && isNum(s[begin])){
            ++begin;
        }
        return begin-1;
    }
    
    int calc(int num1, int num2, char opt){
        int ret;
        switch (opt){
            case '+':
                ret = num1 + num2;
                break;
            case '-':
                ret = num1 - num2;
                break;
            case '*':
                ret = num1 * num2;
                break;
            case '/':
                ret = num1 / num2;
                break;
        }
        return ret;
    }
    
    int calculate(string s) {
        stack<int> nums_stack;
        stack<char> opt_stack;
        unordered_map<char, int> priority;
        priority['+'] = 0;
        priority['-'] = 0;
        priority['*'] = 1;
        priority['/'] = 1;
        
        
        for (int i = 0; i < s.size(); ++i){
            if (isOpt(s[i])){
                if (!opt_stack.empty()){
                    if (priority[s[i]] > priority[opt_stack.top()]){
                        opt_stack.push(s[i]);
                    }else{
                        int num2 = nums_stack.top(); nums_stack.pop();
                        int num1 = nums_stack.top(); nums_stack.pop();
                        char opt = opt_stack.top(); opt_stack.pop();
                        nums_stack.push(calc(num1, num2, opt));
                        --i;
                    }
                }else{
                    opt_stack.push(s[i]);
                }
            }else if (isNum(s[i])){
                int num_end = getNumEnd(s, i);
                nums_stack.push(stoi(s.substr(i,num_end-i+1)));
                i = num_end;
            }
        }
        
        while (!opt_stack.empty()){
            int num2 = nums_stack.top(); nums_stack.pop();
            int num1 = nums_stack.top(); nums_stack.pop();
            char opt = opt_stack.top(); opt_stack.pop();
            nums_stack.push(calc(num1, num2, opt));
        }
    
        return nums_stack.top();
    }
    
};

优化之后:

template<typename T>
class my_stack {
private:
    T* vec;
    int i;
public:
    my_stack(int size) :vec(new T[size]), i(-1) {
        
    }
    
    void push(T e){
        vec[++i] = e;
    }
    
    void pop(){
        --i;
    }
    
    T top(){
        return vec[i];
    }
    
    bool empty(){
        return i <= -1;
    }
};

class Solution {
public:
    bool isOpt(char c){
        if (c == '+' || c == '-' || c == '*' || c == '/'){
            return true;
        }
        return false;
    }
    
    bool isNum(char c){
        if (c >= '0' && c <= '9'){
            return true;
        }
        return false;
    }
    
    int getNumEnd(string &s, int begin){
        while (begin < s.size() && isNum(s[begin])){
            ++begin;
        }
        return begin-1;
    }
    
    int calc(int num1, int num2, char opt){
        int ret;
        switch (opt){
            case '+':
                ret = num1 + num2;
                break;
            case '-':
                ret = num1 - num2;
                break;
            case '*':
                ret = num1 * num2;
                break;
            case '/':
                ret = num1 / num2;
                break;
        }
        return ret;
    }
    
    int calculate(string s) {
        my_stack<int> nums_stack(3);
        my_stack<char> opt_stack(2);
        
        unordered_map<char, int> priority;
        priority['+'] = 0;
        priority['-'] = 0;
        priority['*'] = 1;
        priority['/'] = 1;
        
        
        for (int i = 0; i < s.size(); ++i){
            if (isOpt(s[i])){
                if (!opt_stack.empty()){
                    if (priority[s[i]] > priority[opt_stack.top()]){
                        opt_stack.push(s[i]);
                    }else{
                        int num2 = nums_stack.top(); nums_stack.pop();
                        int num1 = nums_stack.top(); nums_stack.pop();
                        char opt = opt_stack.top(); opt_stack.pop();
                        nums_stack.push(calc(num1, num2, opt));
                        --i;
                    }
                }else{
                    opt_stack.push(s[i]);
                }
            }else if (isNum(s[i])){
                int num_end = getNumEnd(s, i);
                nums_stack.push(stoi(s.substr(i,num_end-i+1)));
                i = num_end;
            }
        }
        
        while (!opt_stack.empty()){
            int num2 = nums_stack.top(); nums_stack.pop();
            int num1 = nums_stack.top(); nums_stack.pop();
            char opt = opt_stack.top(); opt_stack.pop();
            
            nums_stack.push(calc(num1, num2, opt));
        }
    
        return nums_stack.top();
    }
    
};

原创文章 299 获赞 2 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zxc120389574/article/details/106089372