Leetcode: Basic Calculator



Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

You may assume that the given expression is always valid.

Some examples:

"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23

Note: Do not use the eval built-in library function.

本以为简单,写起来发现比较麻烦。堆栈的思想,先计算括号内的。虽然只有加减法,从左到右的顺序也得必须保证。

class Solution {
public:
    int calculate(string s) {
        stack<char> tokens;
        stack<int> nums;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
                tokens.push(s[i]);
            }
            else if (s[i] == ')') {
                nums.push(calOneStep(tokens, nums));
                tokens.pop();
            }
            else {
                int num = 0;
                bool validNum = false;
                while (i < s.size() && isdigit(s[i])) {
                    num = num * 10 + (s[i++] - '0');
                    validNum = true;
                }
                    
                if (validNum) {
                    --i;
                    nums.push(num);
                }
            }
        }
            
        return calOneStep(tokens, nums);
    }
        
private:
    int calOneStep(stack<char>& tokens, stack<int>& nums) {
        stack<char> orderedTokens;
        stack<int> orderedNums;
        while (!tokens.empty() && tokens.top() != '(') {
            orderedTokens.push(tokens.top());
            tokens.pop();
            orderedNums.push(nums.top());
            nums.pop();
        }
        orderedNums.push(nums.top());
        nums.pop();
            
        while (!orderedTokens.empty())
        {
            char token = orderedTokens.top();
            orderedTokens.pop();
            int num1 = orderedNums.top();
            orderedNums.pop();
            int num2 = orderedNums.top();
            orderedNums.pop();
            int result = (token == '+') ? num1 + num2 : num1 - num2;
            orderedNums.push(result);
        }
        
        return orderedNums.top();
    }
};

堆栈保证从左到右的顺序需要反转一下,比较耗时。可以用数组代替。

class Solution {
public:
    int calculate(string s) {
        vector<int> nums;
        vector<char> tokens;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
                tokens.push_back(s[i]);
            }
            else if (s[i] == ')') {
                int startToken = tokens.size() - 1;
                for (; startToken >= 0 && tokens[startToken] != '('; --startToken);
                int startNum = nums.size() - (tokens.size() - startToken);
                int result = nums[startNum];
                for (int iToken = startToken + 1, iNum = startNum + 1; iToken < tokens.size(); ++iToken, ++iNum) {
                    if (tokens[iToken] == '+') {
                        result += nums[iNum];
                    }
                    else {
                        result -= nums[iNum];
                    }
                }
                tokens.resize(startToken);
                nums.resize(startNum);
                nums.push_back(result);
            }
            else {
                int num = 0;
                bool validNum = false;
                while (i < s.size() && isdigit(s[i])) {
                    num = num * 10 + (s[i++] - '0');
                    validNum = true;
                }
                    
                if (validNum) {
                    --i;
                    nums.push_back(num);
                }
            }
        }
        
        int result = nums[0];
        for (int iToken = 0, iNum = 1; iToken < tokens.size(); ++iToken, ++iNum) {
            if (tokens[iToken] == '+') {
                result += nums[iNum];
            }
            else {
                result -= nums[iNum];
            }
        }
            
        return result;
    }
};


再有一种方法,只要不是 “(” 或者 “)” 就立马计算,只保存结果。这也避免了堆栈反转,因为只有两个数的加减运算。

class Solution {
public:
    int calculate(string s) {
        stack<char> tokens;
        stack<int> nums;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '+' || s[i] == '-' || s[i] == '(') {
                tokens.push(s[i]);
            }
            else if (s[i] == ')') {
                tokens.pop();
                while (!tokens.empty() && tokens.top() != '(') {
                    int num2 = nums.top();
                    nums.pop();
                    int num1 = nums.top();
                    nums.pop();
                    int result = (tokens.top() == '+') ? num1 + num2 : num1 - num2;
                    nums.push(result);
                    tokens.pop();
                }
            }
            else {
                int num = 0;
                bool validNum = false;
                while (i < s.size() && isdigit(s[i])) {
                    num = num * 10 + (s[i++] - '0');
                    validNum = true;
                }
                    
                if (validNum) {
                    --i;
                    if (!tokens.empty() && tokens.top() != '(') {
                        int num1 = nums.top();
                        nums.pop();
                        int result = (tokens.top() == '+') ? num1 + num : num1 - num;
                        nums.push(result);
                        tokens.pop();
                    }
                    else {
                        nums.push(num);
                    }
                }
            }
        }
            
        return nums.top();
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值