LeetCode No.224 Basic Calculator 题解

本文介绍了一个基本计算器的设计与实现,能够解析并计算包含括号、加减运算的简单数学表达式。利用栈数据结构处理运算符优先级,通过遍历字符串进行逐个字符解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述


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.


题目分析

题目大意就是做一个简单的Calculator,完成简单的+,-,(,)的运算。
很明显又是一个 Hard 的水题。
直接用数据结构的栈即做完之后可秒杀之。
作为题解还是稍微解释一下吧。
遍历一遍字符串,根据不同的字符来不同处理。 具体如下:
* 若是(,直接入符号栈。
* 若是+, -, 弹出栈顶之前的所有+,-,并取操作数出来进行运算。 最后把该符号压入符号栈。
* 若是),弹出栈顶并计算之直到栈顶为(,最后弹出(
* 若是backspace, 不处理
* 若是其他(保证合法的情况下,只可能是数字了),对字符串分析取出整个数字(有可能不止一位),并压入数字栈。
* 遍历完成之后, 若符号栈还有符号,取出运算即可。

大概做法如上。
但是关键在于程序进行模块化的时候如何不超时是一个问题。当然若是只是写在一个函数中(不用其他辅助函数的话) 没这个问题。
我用的C++, 相对起来处理起来方便一点。 其一是不用考虑字符串的长度用string即可。传入参数的时候尽量采用引用传递。特别是对“`stack, string““这种需要调用构造函数的类型。

下面是具体代码。注意只要任何一个地方不加引用传递就会超时。


#include <stack>
#include <iostream> 
using namespace std;

class Solution {
public:
    int calculate(string s) {
        stack<char> ope;
        stack<int> num;
        int i = 0, ans = 0;
        while (i < s.size()) {
            switch(s[i]) {
                case '(': 
                    ope.push(s[i]);
                    break;
                case ')':
                    bracket_pop(ope, num);
                    break;
                case '+':
                    ope_pop(ope, num, '+');
                    break;
                case '-':
                    ope_pop(ope, num, '-');
                    break;
                case ' ':
                    break;
                    //do nothing;
                default:
                    //number
                    push_num(s, i, num);
                    break;
            }
            ++i;
        }
            if (!ope.empty()) {
                ope_pop(ope, num, '#');
            }
            return num.top();
        }
        inline void bracket_pop(stack<char> &ope, stack<int> &num) {
            while (ope.top() != '(') {
                ope_pop(ope, num, '#');
            }
            ope.pop();
        }
        inline void ope_pop(stack<char> &ope, stack<int> &num, char x) {
            if (ope.empty() || ope.top() == '(' ) {
                ope.push(x);
            return;
        }
        int num2 = num.top();
        num.pop();
        int num1 = num.top();
        num.pop();
        if (ope.top() == '+') {
            num.push(num1 + num2);
        } 
        else {
            num.push(num1 - num2);
        }
        ope.pop();
        if (x != '#')
            ope.push(x);
        return;
    }
    inline void push_num(string &s, int &i, stack<int> &num) {
        int k = 0;
        while (s[i] >= '0' && s[i] <= '9') {
            k = k * 10 + (s[i] - '0');
            i++;
        }
        i--;
        num.push(k);
        return;
    }
};

其他细节

  • 这道题只要求+, -的处理。 事实上很多地方并不需要用到while,因为一定只会弹出一次。
  • 即使用inline函数和引用传递, 调用函数还是要一定的时间开销的。 如果要保证效率还是写在一个函数中比较好。

The End.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值