【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();
    }
    
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章