224. 基本计算器【 力扣(LeetCode) 】

一、题目描述

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

二、测试用例

示例 1:

cpp 复制代码
输入:s = "1 + 1"
输出:2

示例 2:

cpp 复制代码
输入:s = " 2-1 + 2 "
输出:3

示例 3:

cpp 复制代码
输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

提示:

cpp 复制代码
1 <= s.length <= 3 * 105
s 由数字、'+'、'-'、'('、')'、和 ' ' 组成
s 表示一个有效的表达式
'+' 不能用作一元运算(例如, "+1" 和 "+(2 + 3)" 无效)
'-' 可以用作一元运算(即 "-1" 和 "-(2 + 3)" 是有效的)
输入中不存在两个连续的操作符
每个数字和运行的计算将适合于一个有符号的 32位 整数

三、解题思路

【注:官方的方法没有怎么复杂,我这个更容易理解一些】

  1. 基本思路:
      先除去算术表达式中的空格,并将对应元素分割,为了区别负号和减号,负号使用 n 表示;将分割好的算术表达式转为逆波兰表达式;最后用栈完成计算。
  2. 具体思路:
    • 格式化算术表达式:遍历字符串,
      • 遇到空格就跳过
      • 遇到数字就拼接到字符串
      • 遇到符号先判断数字拼接的字符串是否为空,不为空,则先存入数字拼接字符串,在存入符号;为空则直接存入符号。
    • 转为逆波兰表达式:遍历格式化的算术表达式,
      • 遇到数字则存入数字栈中
      • 遇到符号则进行判断:
        • 符号栈 为空,符号为左括号,符号优先级小于 符号栈 顶元素------符号入栈
        • 符号为右括号------将符号栈中元素依次弹入到数字栈中,直到遇到左括号为止
        • 符号优先级大于等于 符号栈 顶元素------弹出符号栈顶元素,存入到数字栈中;再将符号入栈
      • 遍历结束后将符号栈中剩余元素弹入到数字栈中
    • 用栈计算逆波兰表达式:详情看文章:150. 逆波兰表达式求值【 力扣(LeetCode) 】 【注意负号的处理即可】

四、参考代码

时间复杂度: O ( n ) \Omicron(n) O(n)

空间复杂度: O ( n ) \Omicron(n) O(n)

cpp 复制代码
class Solution {
public:
    map<string, int> op_set = {
        {"n", 1}, {"+", 1}, {"-", 1}, {"(", 2}, {")", 2}};

    vector<string> trim(string s) {  // 将算术表达分割并删去空格
        vector<string> ans;
        string t = "";

        for (auto c : s) {
            if (isdigit(c)) {
                t += c;
            } else if (c != ' ') {
                if (t != "") {
                    ans.push_back(t);
                    t = "";
                }
                if (c == '-' && (ans.empty() || ans.back() == "(")) { // 负号的情况
                    c = 'n';
                }
                ans.push_back(string(1, c));
            }
        }
        if (t != "") {
            ans.push_back(t);
        }

        return ans;
    }

    vector<string> s2nbl(vector<string> s) { // 将分割后的字符串转为逆波兰表达式
        vector<string> num, op;
        string t = "";

        for (auto& c : s) {
            if (op_set.count(c) == 1) {
                if (op.empty() || c == "(" || op_set[c] < op_set[op.back()]) {
                    op.push_back(c);
                } else {
                    if (c == ")") {
                        while (op.back() != "(") {
                            num.push_back(op.back());
                            op.pop_back();
                        }
                        op.pop_back();
                    } else {
                        num.push_back(op.back());
                        op.pop_back();
                        op.push_back(c);
                    }
                }
            } else {
                num.push_back(c);
            }
        }
        while (!op.empty()) {
            num.push_back(op.back());
            op.pop_back();
        }

        return num;
    }

    int calculate(string s) {
        int a, b;
        vector<int> num;
        vector<string> strs = s2nbl(trim(s));

        for (auto& str : strs) {
            if (op_set.count(str) == 1) {
                a = num.back();
                num.pop_back();
                if (str != "n") {
                    b = num.back();
                    num.pop_back();
                }
                if (str == "+")
                    num.push_back(a + b);
                else if (str == "-")
                    num.push_back(b - a);
                else
                    num.push_back(-a);
            } else {
                istringstream is(str);
                is >> a;
                num.push_back(a);
            }
        }

        return num.back();
    }
};
相关推荐
LCG元1 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
唐诺3 小时前
几种广泛使用的 C++ 编译器
c++·编译器
XH华3 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子4 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
冷眼看人间恩怨4 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
菜鸡中的奋斗鸡→挣扎鸡4 小时前
滑动窗口 + 算法复习
数据结构·算法
红龙创客4 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin4 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin