题目描述
题目链接:力扣 227. 基本计算器 II
题目描述:给你一个字符串表达式 s,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。你可以假设给定的表达式总是有效的。所有中间结果将在 [-2^31, 2^31 - 1] 的范围内。注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()。
示例 1: 输入:s = "3+2*2" 输出:7
示例 2: 输入:s = " 3/2 " 输出:1
示例 3: 输入:s = " 3+5 / 2 " 输出:5
提示: 1 <= s.length <= 3 * 10^5 s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开 s 表示一个有效表达式 表达式中的所有整数都是非负整数,且在范围 [0, 2^31 - 1] 内 题目数据保证答案是一个 32-bit 整数
算法原理
这道题的核心是处理加减乘除的优先级问题。由于题目不含括号,我们可以简化逻辑,用一个栈加一个符号变量就能高效完成计算。
核心逻辑:化繁为简的优先级处理
- 用一个栈存储最终需要'加减求和'的数字(将减法转化为加负数,统一运算逻辑);
- 用一个字符变量记录当前数字的前导符号(默认第一个数字的符号为
+,确保操作统一); - 遍历字符串时,遇到低优先级的'加减'直接将数字(或其相反数)入栈;遇到高优先级的'乘除',则取出栈顶元素与当前数字计算后,将结果重新压入栈,实现'先算乘除'的优先级要求。
分步模拟:模拟计算全流程
结合示例表达式 +3+5*22-5+3/2,我们一步步看栈的工作流程:
- 初始化与统一规则:为了方便后续操作统一,我们将第一个数字的符号
ch = '+',所有数字都需要和'前一个运算符'绑定。遍历到第一个数字3,因符号为+,直接将3压入栈,此时栈:[3]。 - 处理高优先级运算(乘):遇到
*(前导符号更新为*),后续数字为22。此时需取出栈顶元素5(假设上下文),与22相乘得110,将110压回栈。 - 处理低优先级运算(减):遇到
-(前导符号更新为-),后续数字为5。加减是同级运算,优先级低于乘除,因此可以先将减法对应的数字转为负数存入栈,最后统一求和。将5取反为-5入栈。 - 处理高优先级运算(除):遇到
/(前导符号更新为/),后续数字为2。取出栈顶元素与2做整数除法得1,压回栈。 - 最终求和:遍历结束后,栈中所有元素求和,即为表达式的结果。
关键细节:多位数与空格处理
- 多位数解析:遍历到数字时,需通过'原数字×10 + 当前字符对应的数值'拼接;
- 空格忽略:遇到空格直接跳过,不影响数字和符号的解析。
算法逻辑总结
通过上述分步模拟,我们可以将复杂的表达式求值过程,提炼为一套清晰、可落地的核心规则:
- 遇到操作符(+、-、*、/):直接更新'当前运算符号'变量 (关键前提:第一个数字默认符号为 );


