题目介绍
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
示例1
输入: s = "1 + 1"
输出: 2
示例2
输入: s = " 2-1 + 2 "
输出: 3
示例3
输入: s = "(1+(4+5+2)-3)+(6+8)"
输出: 23
提示:
1 <= s.length <= 3 * 105s由数字、'+'、'-'、'('、')'、和' '组成s表示一个有效的表达式 leetcode-224 基本计算器
b站视频
解题思路
本题由于有括号参与计算,根据小学知识
如果是顺序计算,如果括号前面的符号是 '-',那么括号中的运算需要改变,如果括号前面的符号是 '+',则括号中的运算不需要改变
如果按运算符的优先级计算,那么应该先执行括号中计算,然后再执行括号外的计算
本文将基于这两种思想,提出两种解决办法
思路一:顺序计算
顺序计算的目的是消掉算式中的括号,需要考虑括号前面的符号,因此,当遇到 '(' 时,将 '(' 前面的符号压入栈中,遇到 ')' 时,将栈顶符号弹出
如果 '(' 前面是 '+',那么括号中的 '+' 按 '+' 计算,'-' 按 '-' 计算
如果 '(' 前面是 '-',那么括号中的 '+' 按 '-' 计算,'+' 按 '-' 计算
由此可得出一般规律,遇到 '-' 时,取栈顶符号的相反符号进行计算,遇到 '+' 时,取栈顶符号进行计算
解题代码
var calculate = function(s) {
// 定义一个符号栈
const sign = [1]
// 定义sum用于保存计算结果,op为当前的运算符,n用于将string类型的数字转化成number类型
let sum = 0, op = 1, n = 0
for (let i = 0; i < s.length; i++) {
// 如果遇到' ',直接跳过
if (s[i] === ' ') continue
// 如果遇到数字,将string转成number
if (s[i] - '0' >= 0 && s[i] - '0' <= 9) {
n = n * 10 + s[i] * 1
continue
}
// 当遇到数字和空格以外的符号,当前数字参与计算
sum += op * n
n = 0
// 如果遇到'-',符号位为栈顶取反
if (s[i] === '-') op = -sign[sign.length - 1]
// 如果遇到'+', 符号位为栈顶值
if (s[i] === '+') op = sign[sign.length - 1]
// 如果遇到'(',将当前的符号位压入栈顶
if (s[i] === '(') sign.push(op)
// 如果遇到')',弹出栈顶的符号位
if (s[i] === ')') sign.pop()
}
// 将最后一个值参与运算
sum += op * n
return sum
};
思路二:双栈法(按运算优先级)
按运算符优先级计算时,我们需要先计算括号内的,再计算括号外的,但是同一层括号的运算可以从左到右进行计算
因此,当没有遇到括号时,从左往右进行计算,当遇到 '(' 时,需要将当前的计算结果和符号先压入栈中,然后计算括号中的式子,当遇到 ')' 时,将数字栈和符号栈中的元素依次弹出进行计算
解题代码
var calculate = function(s) {
// 定义数字栈,符号栈用于保存数字和符号
const nums = [], opts = []
// 定义sum用于保存阶段性的和,定义n用于将每个参与计算的数从string转为number,定义sign表示符号位
let sum = 0, n = 0, sign = 1
for (let i = 0; i < s.length; i++) {
// 跳过s中的' '
if (s[i] === ' ') continue
// 遇到数字时,将string类型的数字转成number
if (s[i] - '0' >= 0 && s[i] - '0' <= 9) {
n = n * 10 + s[i] * 1
while (s[i + 1] !== ' ' && s[i + 1] - '0' >= 0 && s[i + 1] - '0' <= 9) {
i++
n = n * 10 + s[i] * 1
}
// 将该值进行计算
sum += sign * n
n = 0
}
// 遇到'+' 或 '-',修改 sign 符号位
if (s[i] === '+' || s[i] === '-') sign = s[i] === '+' ? 1 : -1
// 如果遇到 '(',说明接下来要计算括号中的内容,将括号外的内容先存起来
if (s[i] === '(') {
nums.push(sum)
sum = 0
opts.push(sign)
sign = 1
}
// 如果遇到 ')',说明括号中的内容计算完毕,将前面保存的值弹出计算
if (s[i] === ')') {
sum = nums.pop() + opts.pop() * sum
}
}
return sum
};
以上就是本题的解答过程,如果大家有什么意见或建议,欢迎留言